blob: b62eed6eda46000de07ed88f79156f50338f7ac9 [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 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 Li719b3bf2016-07-22 00:38:29 +090026import org.onosproject.lisp.msg.types.LispAfiAddress;
27
28import java.util.List;
Jian Li451175e2016-07-19 23:22:20 +090029
Jian Li20850d32016-08-04 02:15:57 +090030import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lie4ba2a42016-08-29 20:24:15 +090031import static com.google.common.base.Preconditions.checkArgument;
32import static com.google.common.base.Preconditions.checkNotNull;
Jian Liedc5db12016-08-23 17:30:19 +090033import static org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
34import static org.onosproject.lisp.msg.protocols.LispEidRecord.EidRecordWriter;
Jian Li20850d32016-08-04 02:15:57 +090035
Jian Li451175e2016-07-19 23:22:20 +090036/**
37 * Default LISP map request message class.
38 */
Jian Lif59c0ad2016-08-02 18:11:30 +090039public final class DefaultLispMapRequest implements LispMapRequest {
40
41 private final long nonce;
42 private final byte recordCount;
43 private final LispAfiAddress sourceEid;
44 private final List<LispAfiAddress> itrRlocs;
45 private final List<LispEidRecord> eidRecords;
46 private final boolean authoritative;
47 private final boolean mapDataPresent;
48 private final boolean probe;
49 private final boolean smr;
50 private final boolean pitr;
51 private final boolean smrInvoked;
52
53 /**
54 * A private constructor that protects object instantiation from external.
55 *
56 * @param nonce nonce
57 * @param recordCount record count number
58 * @param sourceEid source EID address
59 * @param itrRlocs a collection of ITR RLOCs
60 * @param eidRecords a collection of EID records
61 * @param authoritative authoritative flag
62 * @param mapDataPresent map data present flag
63 * @param probe probe flag
64 * @param smr smr flag
65 * @param pitr pitr flag
66 * @param smrInvoked smrInvoked flag
67 */
68 private DefaultLispMapRequest(long nonce, byte recordCount, LispAfiAddress sourceEid,
69 List<LispAfiAddress> itrRlocs, List<LispEidRecord> eidRecords,
70 boolean authoritative, boolean mapDataPresent, boolean probe,
71 boolean smr, boolean pitr, boolean smrInvoked) {
72 this.nonce = nonce;
73 this.recordCount = recordCount;
74 this.sourceEid = sourceEid;
75 this.itrRlocs = itrRlocs;
76 this.eidRecords = eidRecords;
77 this.authoritative = authoritative;
78 this.mapDataPresent = mapDataPresent;
79 this.probe = probe;
80 this.smr = smr;
81 this.pitr = pitr;
82 this.smrInvoked = smrInvoked;
83 }
84
Jian Li451175e2016-07-19 23:22:20 +090085 @Override
86 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090087 return LispType.LISP_MAP_REQUEST;
Jian Li451175e2016-07-19 23:22:20 +090088 }
89
90 @Override
91 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090092 // TODO: serialize LispMapRequest message
Jian Li451175e2016-07-19 23:22:20 +090093 }
94
95 @Override
96 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090097 return new DefaultRequestBuilder();
Jian Li451175e2016-07-19 23:22:20 +090098 }
Jian Li719b3bf2016-07-22 00:38:29 +090099
100 @Override
101 public boolean isAuthoritative() {
Jian Liedc5db12016-08-23 17:30:19 +0900102 return authoritative;
Jian Lif59c0ad2016-08-02 18:11:30 +0900103 }
104
105 @Override
106 public boolean isMapDataPresent() {
Jian Liedc5db12016-08-23 17:30:19 +0900107 return mapDataPresent;
Jian Li719b3bf2016-07-22 00:38:29 +0900108 }
109
110 @Override
111 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +0900112 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +0900113 }
114
115 @Override
116 public boolean isSmr() {
Jian Liedc5db12016-08-23 17:30:19 +0900117 return smr;
Jian Li719b3bf2016-07-22 00:38:29 +0900118 }
119
120 @Override
121 public boolean isPitr() {
Jian Liedc5db12016-08-23 17:30:19 +0900122 return pitr;
Jian Li719b3bf2016-07-22 00:38:29 +0900123 }
124
125 @Override
126 public boolean isSmrInvoked() {
Jian Liedc5db12016-08-23 17:30:19 +0900127 return smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900128 }
129
130 @Override
131 public byte getRecordCount() {
Jian Liedc5db12016-08-23 17:30:19 +0900132 return recordCount;
Jian Li719b3bf2016-07-22 00:38:29 +0900133 }
134
135 @Override
136 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +0900137 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900138 }
139
140 @Override
141 public LispAfiAddress getSourceEid() {
Jian Liedc5db12016-08-23 17:30:19 +0900142 return sourceEid;
Jian Li719b3bf2016-07-22 00:38:29 +0900143 }
144
145 @Override
146 public List<LispAfiAddress> getItrRlocs() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900147 return ImmutableList.copyOf(itrRlocs);
Jian Li719b3bf2016-07-22 00:38:29 +0900148 }
149
150 @Override
Jian Li10a09062016-07-26 23:58:50 +0900151 public List<LispEidRecord> getEids() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900152 return ImmutableList.copyOf(eidRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900153 }
154
Jian Li20850d32016-08-04 02:15:57 +0900155 @Override
156 public String toString() {
157 return toStringHelper(this)
158 .add("type", getType())
159 .add("nonce", nonce)
160 .add("recordCount", recordCount)
161 .add("source EID", sourceEid)
162 .add("ITR rlocs", itrRlocs)
163 .add("EID records", eidRecords)
164 .add("authoritative", authoritative)
165 .add("mapDataPresent", mapDataPresent)
166 .add("probe", probe)
167 .add("SMR", smr)
168 .add("Proxy ITR", pitr)
169 .add("SMR Invoked", smrInvoked).toString();
170 }
171
172 @Override
173 public boolean equals(Object o) {
174 if (this == o) {
175 return true;
176 }
177 if (o == null || getClass() != o.getClass()) {
178 return false;
179 }
180 DefaultLispMapRequest that = (DefaultLispMapRequest) o;
181 return Objects.equal(nonce, that.nonce) &&
182 Objects.equal(recordCount, that.recordCount) &&
183 Objects.equal(sourceEid, that.sourceEid) &&
Jian Li20850d32016-08-04 02:15:57 +0900184 Objects.equal(authoritative, that.authoritative) &&
185 Objects.equal(mapDataPresent, that.mapDataPresent) &&
186 Objects.equal(probe, that.probe) &&
187 Objects.equal(smr, that.smr) &&
188 Objects.equal(pitr, that.pitr) &&
189 Objects.equal(smrInvoked, that.smrInvoked);
190 }
191
192 @Override
193 public int hashCode() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900194 return Objects.hashCode(nonce, recordCount, sourceEid, authoritative,
195 mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li20850d32016-08-04 02:15:57 +0900196 }
197
Jian Li719b3bf2016-07-22 00:38:29 +0900198 public static final class DefaultRequestBuilder implements RequestBuilder {
199
Jian Lif59c0ad2016-08-02 18:11:30 +0900200 private long nonce;
201 private byte recordCount;
202 private LispAfiAddress sourceEid;
203 private List<LispAfiAddress> itrRlocs = Lists.newArrayList();
204 private List<LispEidRecord> eidRecords = Lists.newArrayList();
205 private boolean authoritative;
206 private boolean mapDataPresent;
207 private boolean probe;
208 private boolean smr;
209 private boolean pitr;
210 private boolean smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900211
212 @Override
213 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900214 return LispType.LISP_MAP_REQUEST;
Jian Li719b3bf2016-07-22 00:38:29 +0900215 }
216
217 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900218 public RequestBuilder withIsAuthoritative(boolean authoritative) {
219 this.authoritative = authoritative;
220 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900221 }
222
223 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900224 public RequestBuilder withIsProbe(boolean probe) {
225 this.probe = probe;
226 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900227 }
228
229 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900230 public RequestBuilder withIsMapDataPresent(boolean mapDataPresent) {
231 this.mapDataPresent = mapDataPresent;
232 return this;
233 }
234
Jian Lif59c0ad2016-08-02 18:11:30 +0900235 @Override
236 public RequestBuilder withIsSmr(boolean smr) {
237 this.smr = smr;
238 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900239 }
240
241 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900242 public RequestBuilder withIsPitr(boolean pitr) {
243 this.pitr = pitr;
244 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900245 }
246
247 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900248 public RequestBuilder withIsSmrInvoked(boolean smrInvoked) {
249 this.smrInvoked = smrInvoked;
250 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900251 }
252
253 @Override
254 public RequestBuilder withRecordCount(byte recordCount) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900255 this.recordCount = recordCount;
256 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900257 }
258
259 @Override
260 public RequestBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900261 this.nonce = nonce;
262 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900263 }
264
265 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900266 public RequestBuilder withSourceEid(LispAfiAddress sourceEid) {
267 this.sourceEid = sourceEid;
268 return this;
269 }
270
271 @Override
Jian Li47671902016-08-11 01:18:18 +0900272 public RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900273
274 if (itrRlocs != null) {
275 this.itrRlocs = ImmutableList.copyOf(itrRlocs);
276 } else {
277 this.itrRlocs = Lists.newArrayList();
278 }
279
Jian Lif59c0ad2016-08-02 18:11:30 +0900280 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900281 }
282
283 @Override
Jian Li47671902016-08-11 01:18:18 +0900284 public RequestBuilder withEidRecords(List<LispEidRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900285
286 if (records != null) {
287 this.eidRecords = ImmutableList.copyOf(records);
288 } else {
289 this.eidRecords = Lists.newArrayList();
290 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900291 return this;
292 }
293
294 @Override
Jian Li525fded2016-08-04 01:15:33 +0900295 public LispMapRequest build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900296
297 checkNotNull(sourceEid, "Must have a source EID");
298 checkArgument((itrRlocs != null) && (itrRlocs.size() > 0), "Must have an ITR RLOC entry");
299
Jian Lif59c0ad2016-08-02 18:11:30 +0900300 return new DefaultLispMapRequest(nonce, recordCount, sourceEid, itrRlocs,
301 eidRecords, authoritative, mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li719b3bf2016-07-22 00:38:29 +0900302 }
303 }
Jian Li26069e22016-08-10 22:00:52 +0900304
305 /**
Jian Liedc5db12016-08-23 17:30:19 +0900306 * A LISP message reader for MapRequest message.
Jian Li26069e22016-08-10 22:00:52 +0900307 */
Jian Liedc5db12016-08-23 17:30:19 +0900308 public static final class RequestReader implements LispMessageReader<LispMapRequest> {
Jian Li26069e22016-08-10 22:00:52 +0900309
Jian Li47671902016-08-11 01:18:18 +0900310 private static final int AUTHORITATIVE_INDEX = 3;
311 private static final int MAP_DATA_PRESENT_INDEX = 2;
312 private static final int PROBE_INDEX = 1;
313 private static final int SMR_INDEX = 0;
314 private static final int PITR_INDEX = 7;
315 private static final int SMR_INVOKED_INDEX = 6;
316
Jian Li26069e22016-08-10 22:00:52 +0900317 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900318 public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900319
320 if (byteBuf.readerIndex() != 0) {
321 return null;
322 }
323
324 byte typeWithFlags = byteBuf.readByte();
325
326 // authoritative -> 1 bit
327 boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);
328
329 // mapDataPresent -> 1 bit
330 boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);
331
332 // probe -> 1 bit
333 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
334
335 // smr -> 1 bit
336 boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);
337
338 byte reservedWithFlags = byteBuf.readByte();
339
340 // pitr -> 1 bit
341 boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);
342
343 // smrInvoked -> 1 bit
344 boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);
345
346 // let's skip reserved field, only obtains ITR counter value
347 // assume that first 3 bits are all set as 0,
348 // remain 5 bits represent Itr Rloc Counter (IRC)
Jian Lie4ba2a42016-08-29 20:24:15 +0900349 int irc = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900350
351 // record count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900352 int recordCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900353
354 // nonce -> 64 bits
355 long nonce = byteBuf.readLong();
356
Jian Lia7b394d2016-08-21 23:11:46 +0900357 LispAfiAddress sourceEid = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900358
Jian Lia7b394d2016-08-21 23:11:46 +0900359 // deserialize a collection of RLOC addresses
360 List<LispAfiAddress> itrRlocs = Lists.newArrayList();
361 for (int i = 0; i < irc; i++) {
362 itrRlocs.add(new LispAfiAddress.AfiAddressReader().readFrom(byteBuf));
363 }
Jian Li47671902016-08-11 01:18:18 +0900364
Jian Lia7b394d2016-08-21 23:11:46 +0900365 // deserialize a collection of EID records
366 List<LispEidRecord> eidRecords = Lists.newArrayList();
367 for (int i = 0; i < recordCount; i++) {
368 eidRecords.add(new LispEidRecord.EidRecordReader().readFrom(byteBuf));
369 }
Jian Li47671902016-08-11 01:18:18 +0900370
371 return new DefaultRequestBuilder()
372 .withIsAuthoritative(authoritative)
373 .withIsMapDataPresent(mapDataPresent)
374 .withIsProbe(probe)
375 .withIsSmr(smr)
376 .withIsPitr(pitr)
377 .withIsSmrInvoked(smrInvoked)
378 .withNonce(nonce)
379 .withRecordCount((byte) recordCount)
Jian Lia7b394d2016-08-21 23:11:46 +0900380 .withSourceEid(sourceEid)
381 .withEidRecords(eidRecords)
382 .withItrRlocs(itrRlocs)
Jian Li47671902016-08-11 01:18:18 +0900383 .build();
Jian Li26069e22016-08-10 22:00:52 +0900384 }
385 }
Jian Liedc5db12016-08-23 17:30:19 +0900386
387 /**
388 * A LISP message writer for MapRequest message.
389 */
390 public static final class RequestWriter implements LispMessageWriter<LispMapRequest> {
391
392 private static final int REQUEST_MSG_TYPE = 1;
393 private static final int REQUEST_SHIFT_BIT = 4;
394
395 private static final int AUTHORITATIVE_SHIFT_BIT = 3;
396 private static final int MAP_DATA_PRESENT_SHIFT_BIT = 2;
397 private static final int PROBE_SHIFT_BIT = 1;
398
399 private static final int PITR_SHIFT_BIT = 7;
400 private static final int SMR_INVOKED_SHIFT_BIT = 6;
401
402 private static final int ENABLE_BIT = 1;
403 private static final int DISABLE_BIT = 0;
404
Jian Liedc5db12016-08-23 17:30:19 +0900405 @Override
406 public void writeTo(ByteBuf byteBuf, LispMapRequest message) throws LispWriterException {
407
408 // specify LISP message type
409 byte msgType = (byte) (REQUEST_MSG_TYPE << REQUEST_SHIFT_BIT);
410
411 // authoritative flag
412 byte authoritative = DISABLE_BIT;
413 if (message.isAuthoritative()) {
414 authoritative = (byte) (ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT);
415 }
416
417 // map data present flag
418 byte mapDataPresent = DISABLE_BIT;
419 if (message.isMapDataPresent()) {
420 mapDataPresent = (byte) (ENABLE_BIT << MAP_DATA_PRESENT_SHIFT_BIT);
421 }
422
423 // probe flag
424 byte probe = DISABLE_BIT;
425 if (message.isProbe()) {
426 probe = (byte) (ENABLE_BIT << PROBE_SHIFT_BIT);
427 }
428
429 // SMR flag
430 byte smr = DISABLE_BIT;
431 if (message.isSmr()) {
432 smr = (byte) ENABLE_BIT;
433 }
434
435 byteBuf.writeByte((byte) (msgType + authoritative + mapDataPresent + probe + smr));
436
437 // PITR flag bit
438 byte pitr = DISABLE_BIT;
439 if (message.isPitr()) {
440 pitr = (byte) (ENABLE_BIT << PITR_SHIFT_BIT);
441 }
442
443 // SMR invoked flag bit
444 byte smrInvoked = DISABLE_BIT;
445 if (message.isSmrInvoked()) {
446 smrInvoked = (byte) (ENABLE_BIT << SMR_INVOKED_SHIFT_BIT);
447 }
448
449 byteBuf.writeByte((byte) (pitr + smrInvoked));
450
Jian Lie4ba2a42016-08-29 20:24:15 +0900451 // ITR Rloc count
452 byteBuf.writeByte((byte) message.getItrRlocs().size());
Jian Liedc5db12016-08-23 17:30:19 +0900453
454 // record count
455 byteBuf.writeByte(message.getRecordCount());
456
457 // nonce
458 byteBuf.writeLong(message.getNonce());
459
460 // Source EID AFI with Source EID address
461 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
462 afiAddressWriter.writeTo(byteBuf, message.getSourceEid());
463
464 // ITR RLOCs
465 List<LispAfiAddress> rlocs = message.getItrRlocs();
466 for (int i = 0; i < rlocs.size(); i++) {
467 afiAddressWriter.writeTo(byteBuf, rlocs.get(i));
468 }
469
470 // EID records
471 EidRecordWriter recordWriter = new EidRecordWriter();
472 List<LispEidRecord> records = message.getEids();
473
474 for (int i = 0; i < records.size(); i++) {
475 recordWriter.writeTo(byteBuf, records.get(i));
476 }
477
478 // TODO: handle Map-Reply record
479 }
480 }
Jian Li451175e2016-07-19 23:22:20 +0900481}