blob: c44c909b956f30d9597cf89ff45e5ef678f57fcc [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 if (itrRlocs != null) {
274 this.itrRlocs = ImmutableList.copyOf(itrRlocs);
Jian Lie4ba2a42016-08-29 20:24:15 +0900275 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900276 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900277 }
278
279 @Override
Jian Li47671902016-08-11 01:18:18 +0900280 public RequestBuilder withEidRecords(List<LispEidRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900281 if (records != null) {
282 this.eidRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900283 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900284 return this;
285 }
286
287 @Override
Jian Li525fded2016-08-04 01:15:33 +0900288 public LispMapRequest build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900289
290 checkNotNull(sourceEid, "Must have a source EID");
291 checkArgument((itrRlocs != null) && (itrRlocs.size() > 0), "Must have an ITR RLOC entry");
292
Jian Lif59c0ad2016-08-02 18:11:30 +0900293 return new DefaultLispMapRequest(nonce, recordCount, sourceEid, itrRlocs,
294 eidRecords, authoritative, mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li719b3bf2016-07-22 00:38:29 +0900295 }
296 }
Jian Li26069e22016-08-10 22:00:52 +0900297
298 /**
Jian Liedc5db12016-08-23 17:30:19 +0900299 * A LISP message reader for MapRequest message.
Jian Li26069e22016-08-10 22:00:52 +0900300 */
Jian Liedc5db12016-08-23 17:30:19 +0900301 public static final class RequestReader implements LispMessageReader<LispMapRequest> {
Jian Li26069e22016-08-10 22:00:52 +0900302
Jian Li47671902016-08-11 01:18:18 +0900303 private static final int AUTHORITATIVE_INDEX = 3;
304 private static final int MAP_DATA_PRESENT_INDEX = 2;
305 private static final int PROBE_INDEX = 1;
306 private static final int SMR_INDEX = 0;
307 private static final int PITR_INDEX = 7;
308 private static final int SMR_INVOKED_INDEX = 6;
309
Jian Li26069e22016-08-10 22:00:52 +0900310 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900311 public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900312
313 if (byteBuf.readerIndex() != 0) {
314 return null;
315 }
316
317 byte typeWithFlags = byteBuf.readByte();
318
319 // authoritative -> 1 bit
320 boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);
321
322 // mapDataPresent -> 1 bit
323 boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);
324
325 // probe -> 1 bit
326 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
327
328 // smr -> 1 bit
329 boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);
330
331 byte reservedWithFlags = byteBuf.readByte();
332
333 // pitr -> 1 bit
334 boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);
335
336 // smrInvoked -> 1 bit
337 boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);
338
339 // let's skip reserved field, only obtains ITR counter value
340 // assume that first 3 bits are all set as 0,
341 // remain 5 bits represent Itr Rloc Counter (IRC)
Jian Lie4ba2a42016-08-29 20:24:15 +0900342 int irc = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900343
344 // record count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900345 int recordCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900346
347 // nonce -> 64 bits
348 long nonce = byteBuf.readLong();
349
Jian Lia7b394d2016-08-21 23:11:46 +0900350 LispAfiAddress sourceEid = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900351
Jian Lia7b394d2016-08-21 23:11:46 +0900352 // deserialize a collection of RLOC addresses
353 List<LispAfiAddress> itrRlocs = Lists.newArrayList();
354 for (int i = 0; i < irc; i++) {
355 itrRlocs.add(new LispAfiAddress.AfiAddressReader().readFrom(byteBuf));
356 }
Jian Li47671902016-08-11 01:18:18 +0900357
Jian Lia7b394d2016-08-21 23:11:46 +0900358 // deserialize a collection of EID records
359 List<LispEidRecord> eidRecords = Lists.newArrayList();
360 for (int i = 0; i < recordCount; i++) {
361 eidRecords.add(new LispEidRecord.EidRecordReader().readFrom(byteBuf));
362 }
Jian Li47671902016-08-11 01:18:18 +0900363
364 return new DefaultRequestBuilder()
365 .withIsAuthoritative(authoritative)
366 .withIsMapDataPresent(mapDataPresent)
367 .withIsProbe(probe)
368 .withIsSmr(smr)
369 .withIsPitr(pitr)
370 .withIsSmrInvoked(smrInvoked)
371 .withNonce(nonce)
372 .withRecordCount((byte) recordCount)
Jian Lia7b394d2016-08-21 23:11:46 +0900373 .withSourceEid(sourceEid)
374 .withEidRecords(eidRecords)
375 .withItrRlocs(itrRlocs)
Jian Li47671902016-08-11 01:18:18 +0900376 .build();
Jian Li26069e22016-08-10 22:00:52 +0900377 }
378 }
Jian Liedc5db12016-08-23 17:30:19 +0900379
380 /**
381 * A LISP message writer for MapRequest message.
382 */
383 public static final class RequestWriter implements LispMessageWriter<LispMapRequest> {
384
385 private static final int REQUEST_MSG_TYPE = 1;
386 private static final int REQUEST_SHIFT_BIT = 4;
387
388 private static final int AUTHORITATIVE_SHIFT_BIT = 3;
389 private static final int MAP_DATA_PRESENT_SHIFT_BIT = 2;
390 private static final int PROBE_SHIFT_BIT = 1;
391
392 private static final int PITR_SHIFT_BIT = 7;
393 private static final int SMR_INVOKED_SHIFT_BIT = 6;
394
395 private static final int ENABLE_BIT = 1;
396 private static final int DISABLE_BIT = 0;
397
Jian Liedc5db12016-08-23 17:30:19 +0900398 @Override
399 public void writeTo(ByteBuf byteBuf, LispMapRequest message) throws LispWriterException {
400
401 // specify LISP message type
402 byte msgType = (byte) (REQUEST_MSG_TYPE << REQUEST_SHIFT_BIT);
403
404 // authoritative flag
405 byte authoritative = DISABLE_BIT;
406 if (message.isAuthoritative()) {
407 authoritative = (byte) (ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT);
408 }
409
410 // map data present flag
411 byte mapDataPresent = DISABLE_BIT;
412 if (message.isMapDataPresent()) {
413 mapDataPresent = (byte) (ENABLE_BIT << MAP_DATA_PRESENT_SHIFT_BIT);
414 }
415
416 // probe flag
417 byte probe = DISABLE_BIT;
418 if (message.isProbe()) {
419 probe = (byte) (ENABLE_BIT << PROBE_SHIFT_BIT);
420 }
421
422 // SMR flag
423 byte smr = DISABLE_BIT;
424 if (message.isSmr()) {
425 smr = (byte) ENABLE_BIT;
426 }
427
428 byteBuf.writeByte((byte) (msgType + authoritative + mapDataPresent + probe + smr));
429
430 // PITR flag bit
431 byte pitr = DISABLE_BIT;
432 if (message.isPitr()) {
433 pitr = (byte) (ENABLE_BIT << PITR_SHIFT_BIT);
434 }
435
436 // SMR invoked flag bit
437 byte smrInvoked = DISABLE_BIT;
438 if (message.isSmrInvoked()) {
439 smrInvoked = (byte) (ENABLE_BIT << SMR_INVOKED_SHIFT_BIT);
440 }
441
442 byteBuf.writeByte((byte) (pitr + smrInvoked));
443
Jian Lie4ba2a42016-08-29 20:24:15 +0900444 // ITR Rloc count
445 byteBuf.writeByte((byte) message.getItrRlocs().size());
Jian Liedc5db12016-08-23 17:30:19 +0900446
447 // record count
448 byteBuf.writeByte(message.getRecordCount());
449
450 // nonce
451 byteBuf.writeLong(message.getNonce());
452
453 // Source EID AFI with Source EID address
454 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
455 afiAddressWriter.writeTo(byteBuf, message.getSourceEid());
456
457 // ITR RLOCs
458 List<LispAfiAddress> rlocs = message.getItrRlocs();
459 for (int i = 0; i < rlocs.size(); i++) {
460 afiAddressWriter.writeTo(byteBuf, rlocs.get(i));
461 }
462
463 // EID records
464 EidRecordWriter recordWriter = new EidRecordWriter();
465 List<LispEidRecord> records = message.getEids();
466
467 for (int i = 0; i < records.size(); i++) {
468 recordWriter.writeTo(byteBuf, records.get(i));
469 }
470
471 // TODO: handle Map-Reply record
472 }
473 }
Jian Li451175e2016-07-19 23:22:20 +0900474}