blob: 21b0c38540adf3e62d166cd63ecdb48c6d061368 [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;
Jian Liedc5db12016-08-23 17:30:19 +090032import static org.onosproject.lisp.msg.protocols.LispEidRecord.EidRecordWriter;
Jian Lif11594a2016-10-31 18:16:02 +090033import static org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
Jian Li20850d32016-08-04 02:15:57 +090034
Jian Li451175e2016-07-19 23:22:20 +090035/**
36 * Default LISP map request message class.
37 */
Jian Liafe2d3f2016-11-01 02:49:07 +090038public final class DefaultLispMapRequest extends AbstractLispMessage
39 implements LispMapRequest {
Jian Lif59c0ad2016-08-02 18:11:30 +090040
41 private final long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090042 private final LispAfiAddress sourceEid;
43 private final List<LispAfiAddress> itrRlocs;
44 private final List<LispEidRecord> eidRecords;
45 private final boolean authoritative;
46 private final boolean mapDataPresent;
47 private final boolean probe;
48 private final boolean smr;
49 private final boolean pitr;
50 private final boolean smrInvoked;
51
Yoonseon Hanca814bf2016-09-12 11:37:48 -070052 static final RequestWriter WRITER;
53 static {
54 WRITER = new RequestWriter();
55 }
56
Jian Lif59c0ad2016-08-02 18:11:30 +090057 /**
58 * A private constructor that protects object instantiation from external.
59 *
60 * @param nonce nonce
Jian Lif59c0ad2016-08-02 18:11:30 +090061 * @param sourceEid source EID address
62 * @param itrRlocs a collection of ITR RLOCs
63 * @param eidRecords a collection of EID records
64 * @param authoritative authoritative flag
65 * @param mapDataPresent map data present flag
66 * @param probe probe flag
67 * @param smr smr flag
68 * @param pitr pitr flag
69 * @param smrInvoked smrInvoked flag
70 */
Jian Li42b3e432016-08-31 01:05:20 +090071 private DefaultLispMapRequest(long nonce, LispAfiAddress sourceEid,
Jian Lif59c0ad2016-08-02 18:11:30 +090072 List<LispAfiAddress> itrRlocs, List<LispEidRecord> eidRecords,
73 boolean authoritative, boolean mapDataPresent, boolean probe,
74 boolean smr, boolean pitr, boolean smrInvoked) {
75 this.nonce = nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090076 this.sourceEid = sourceEid;
77 this.itrRlocs = itrRlocs;
78 this.eidRecords = eidRecords;
79 this.authoritative = authoritative;
80 this.mapDataPresent = mapDataPresent;
81 this.probe = probe;
82 this.smr = smr;
83 this.pitr = pitr;
84 this.smrInvoked = smrInvoked;
85 }
86
Jian Li451175e2016-07-19 23:22:20 +090087 @Override
88 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090089 return LispType.LISP_MAP_REQUEST;
Jian Li451175e2016-07-19 23:22:20 +090090 }
91
92 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070093 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
94 WRITER.writeTo(byteBuf, this);
Jian Li451175e2016-07-19 23:22:20 +090095 }
96
97 @Override
98 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090099 return new DefaultRequestBuilder();
Jian Li451175e2016-07-19 23:22:20 +0900100 }
Jian Li719b3bf2016-07-22 00:38:29 +0900101
102 @Override
103 public boolean isAuthoritative() {
Jian Liedc5db12016-08-23 17:30:19 +0900104 return authoritative;
Jian Lif59c0ad2016-08-02 18:11:30 +0900105 }
106
107 @Override
108 public boolean isMapDataPresent() {
Jian Liedc5db12016-08-23 17:30:19 +0900109 return mapDataPresent;
Jian Li719b3bf2016-07-22 00:38:29 +0900110 }
111
112 @Override
113 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +0900114 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +0900115 }
116
117 @Override
118 public boolean isSmr() {
Jian Liedc5db12016-08-23 17:30:19 +0900119 return smr;
Jian Li719b3bf2016-07-22 00:38:29 +0900120 }
121
122 @Override
123 public boolean isPitr() {
Jian Liedc5db12016-08-23 17:30:19 +0900124 return pitr;
Jian Li719b3bf2016-07-22 00:38:29 +0900125 }
126
127 @Override
128 public boolean isSmrInvoked() {
Jian Liedc5db12016-08-23 17:30:19 +0900129 return smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900130 }
131
132 @Override
Jian Li42b3e432016-08-31 01:05:20 +0900133 public int getRecordCount() {
134 return eidRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +0900135 }
136
137 @Override
138 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +0900139 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900140 }
141
142 @Override
143 public LispAfiAddress getSourceEid() {
Jian Liedc5db12016-08-23 17:30:19 +0900144 return sourceEid;
Jian Li719b3bf2016-07-22 00:38:29 +0900145 }
146
147 @Override
148 public List<LispAfiAddress> getItrRlocs() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900149 return ImmutableList.copyOf(itrRlocs);
Jian Li719b3bf2016-07-22 00:38:29 +0900150 }
151
152 @Override
Jian Li10a09062016-07-26 23:58:50 +0900153 public List<LispEidRecord> getEids() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900154 return ImmutableList.copyOf(eidRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900155 }
156
Jian Li20850d32016-08-04 02:15:57 +0900157 @Override
158 public String toString() {
159 return toStringHelper(this)
160 .add("type", getType())
161 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900162 .add("source EID", sourceEid)
163 .add("ITR rlocs", itrRlocs)
164 .add("EID records", eidRecords)
165 .add("authoritative", authoritative)
166 .add("mapDataPresent", mapDataPresent)
167 .add("probe", probe)
168 .add("SMR", smr)
169 .add("Proxy ITR", pitr)
170 .add("SMR Invoked", smrInvoked).toString();
171 }
172
173 @Override
174 public boolean equals(Object o) {
175 if (this == o) {
176 return true;
177 }
178 if (o == null || getClass() != o.getClass()) {
179 return false;
180 }
181 DefaultLispMapRequest that = (DefaultLispMapRequest) o;
182 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900183 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 Li42b3e432016-08-31 01:05:20 +0900194 return Objects.hashCode(nonce, sourceEid, authoritative,
Jian Lie4ba2a42016-08-29 20:24:15 +0900195 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;
Jian Lif59c0ad2016-08-02 18:11:30 +0900201 private LispAfiAddress sourceEid;
202 private List<LispAfiAddress> itrRlocs = Lists.newArrayList();
203 private List<LispEidRecord> eidRecords = Lists.newArrayList();
204 private boolean authoritative;
205 private boolean mapDataPresent;
206 private boolean probe;
207 private boolean smr;
208 private boolean pitr;
209 private boolean smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900210
211 @Override
212 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900213 return LispType.LISP_MAP_REQUEST;
Jian Li719b3bf2016-07-22 00:38:29 +0900214 }
215
216 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900217 public RequestBuilder withIsAuthoritative(boolean authoritative) {
218 this.authoritative = authoritative;
219 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900220 }
221
222 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900223 public RequestBuilder withIsProbe(boolean probe) {
224 this.probe = probe;
225 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900226 }
227
228 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900229 public RequestBuilder withIsMapDataPresent(boolean mapDataPresent) {
230 this.mapDataPresent = mapDataPresent;
231 return this;
232 }
233
Jian Lif59c0ad2016-08-02 18:11:30 +0900234 @Override
235 public RequestBuilder withIsSmr(boolean smr) {
236 this.smr = smr;
237 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900238 }
239
240 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900241 public RequestBuilder withIsPitr(boolean pitr) {
242 this.pitr = pitr;
243 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900244 }
245
246 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900247 public RequestBuilder withIsSmrInvoked(boolean smrInvoked) {
248 this.smrInvoked = smrInvoked;
249 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900250 }
251
252 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900253 public RequestBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900254 this.nonce = nonce;
255 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900256 }
257
258 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900259 public RequestBuilder withSourceEid(LispAfiAddress sourceEid) {
260 this.sourceEid = sourceEid;
261 return this;
262 }
263
264 @Override
Jian Li47671902016-08-11 01:18:18 +0900265 public RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900266 if (itrRlocs != null) {
267 this.itrRlocs = ImmutableList.copyOf(itrRlocs);
Jian Lie4ba2a42016-08-29 20:24:15 +0900268 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900269 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900270 }
271
272 @Override
Jian Li47671902016-08-11 01:18:18 +0900273 public RequestBuilder withEidRecords(List<LispEidRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900274 if (records != null) {
275 this.eidRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900276 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900277 return this;
278 }
279
280 @Override
Jian Li525fded2016-08-04 01:15:33 +0900281 public LispMapRequest build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900282
Jian Lie4ba2a42016-08-29 20:24:15 +0900283 checkArgument((itrRlocs != null) && (itrRlocs.size() > 0), "Must have an ITR RLOC entry");
284
Jian Li42b3e432016-08-31 01:05:20 +0900285 return new DefaultLispMapRequest(nonce, sourceEid, itrRlocs, eidRecords,
286 authoritative, mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li719b3bf2016-07-22 00:38:29 +0900287 }
288 }
Jian Li26069e22016-08-10 22:00:52 +0900289
290 /**
Jian Liedc5db12016-08-23 17:30:19 +0900291 * A LISP message reader for MapRequest message.
Jian Li26069e22016-08-10 22:00:52 +0900292 */
Jian Liedc5db12016-08-23 17:30:19 +0900293 public static final class RequestReader implements LispMessageReader<LispMapRequest> {
Jian Li26069e22016-08-10 22:00:52 +0900294
Jian Li47671902016-08-11 01:18:18 +0900295 private static final int AUTHORITATIVE_INDEX = 3;
296 private static final int MAP_DATA_PRESENT_INDEX = 2;
297 private static final int PROBE_INDEX = 1;
298 private static final int SMR_INDEX = 0;
299 private static final int PITR_INDEX = 7;
300 private static final int SMR_INVOKED_INDEX = 6;
301
Jian Li26069e22016-08-10 22:00:52 +0900302 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900303 public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900304
305 if (byteBuf.readerIndex() != 0) {
306 return null;
307 }
308
309 byte typeWithFlags = byteBuf.readByte();
310
311 // authoritative -> 1 bit
312 boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);
313
314 // mapDataPresent -> 1 bit
315 boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);
316
317 // probe -> 1 bit
318 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
319
320 // smr -> 1 bit
321 boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);
322
323 byte reservedWithFlags = byteBuf.readByte();
324
325 // pitr -> 1 bit
326 boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);
327
328 // smrInvoked -> 1 bit
329 boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);
330
331 // let's skip reserved field, only obtains ITR counter value
332 // assume that first 3 bits are all set as 0,
333 // remain 5 bits represent Itr Rloc Counter (IRC)
Jian Lie4ba2a42016-08-29 20:24:15 +0900334 int irc = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900335
336 // record count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900337 int recordCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900338
339 // nonce -> 64 bits
340 long nonce = byteBuf.readLong();
341
Jian Lia7b394d2016-08-21 23:11:46 +0900342 LispAfiAddress sourceEid = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900343
Jian Lia7b394d2016-08-21 23:11:46 +0900344 // deserialize a collection of RLOC addresses
345 List<LispAfiAddress> itrRlocs = Lists.newArrayList();
Jian Lif11594a2016-10-31 18:16:02 +0900346 for (int i = 0; i < irc + 1; i++) {
Jian Lia7b394d2016-08-21 23:11:46 +0900347 itrRlocs.add(new LispAfiAddress.AfiAddressReader().readFrom(byteBuf));
348 }
Jian Li47671902016-08-11 01:18:18 +0900349
Jian Lia7b394d2016-08-21 23:11:46 +0900350 // deserialize a collection of EID records
351 List<LispEidRecord> eidRecords = Lists.newArrayList();
352 for (int i = 0; i < recordCount; i++) {
353 eidRecords.add(new LispEidRecord.EidRecordReader().readFrom(byteBuf));
354 }
Jian Li47671902016-08-11 01:18:18 +0900355
356 return new DefaultRequestBuilder()
357 .withIsAuthoritative(authoritative)
358 .withIsMapDataPresent(mapDataPresent)
359 .withIsProbe(probe)
360 .withIsSmr(smr)
361 .withIsPitr(pitr)
362 .withIsSmrInvoked(smrInvoked)
363 .withNonce(nonce)
Jian Lia7b394d2016-08-21 23:11:46 +0900364 .withSourceEid(sourceEid)
365 .withEidRecords(eidRecords)
366 .withItrRlocs(itrRlocs)
Jian Li47671902016-08-11 01:18:18 +0900367 .build();
Jian Li26069e22016-08-10 22:00:52 +0900368 }
369 }
Jian Liedc5db12016-08-23 17:30:19 +0900370
371 /**
372 * A LISP message writer for MapRequest message.
373 */
374 public static final class RequestWriter implements LispMessageWriter<LispMapRequest> {
375
Jian Liedc5db12016-08-23 17:30:19 +0900376 private static final int REQUEST_SHIFT_BIT = 4;
377
378 private static final int AUTHORITATIVE_SHIFT_BIT = 3;
379 private static final int MAP_DATA_PRESENT_SHIFT_BIT = 2;
380 private static final int PROBE_SHIFT_BIT = 1;
381
382 private static final int PITR_SHIFT_BIT = 7;
383 private static final int SMR_INVOKED_SHIFT_BIT = 6;
384
385 private static final int ENABLE_BIT = 1;
386 private static final int DISABLE_BIT = 0;
387
Jian Liedc5db12016-08-23 17:30:19 +0900388 @Override
389 public void writeTo(ByteBuf byteBuf, LispMapRequest message) throws LispWriterException {
390
391 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900392 byte msgType = (byte) (LispType.LISP_MAP_REQUEST.getTypeCode() << REQUEST_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900393
394 // authoritative flag
395 byte authoritative = DISABLE_BIT;
396 if (message.isAuthoritative()) {
397 authoritative = (byte) (ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT);
398 }
399
400 // map data present flag
401 byte mapDataPresent = DISABLE_BIT;
402 if (message.isMapDataPresent()) {
403 mapDataPresent = (byte) (ENABLE_BIT << MAP_DATA_PRESENT_SHIFT_BIT);
404 }
405
406 // probe flag
407 byte probe = DISABLE_BIT;
408 if (message.isProbe()) {
409 probe = (byte) (ENABLE_BIT << PROBE_SHIFT_BIT);
410 }
411
412 // SMR flag
413 byte smr = DISABLE_BIT;
414 if (message.isSmr()) {
415 smr = (byte) ENABLE_BIT;
416 }
417
418 byteBuf.writeByte((byte) (msgType + authoritative + mapDataPresent + probe + smr));
419
420 // PITR flag bit
421 byte pitr = DISABLE_BIT;
422 if (message.isPitr()) {
423 pitr = (byte) (ENABLE_BIT << PITR_SHIFT_BIT);
424 }
425
426 // SMR invoked flag bit
427 byte smrInvoked = DISABLE_BIT;
428 if (message.isSmrInvoked()) {
429 smrInvoked = (byte) (ENABLE_BIT << SMR_INVOKED_SHIFT_BIT);
430 }
431
432 byteBuf.writeByte((byte) (pitr + smrInvoked));
433
Jian Lie4ba2a42016-08-29 20:24:15 +0900434 // ITR Rloc count
Jian Lif11594a2016-10-31 18:16:02 +0900435 byteBuf.writeByte((byte) message.getItrRlocs().size() - 1);
Jian Liedc5db12016-08-23 17:30:19 +0900436
437 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900438 byteBuf.writeByte(message.getEids().size());
Jian Liedc5db12016-08-23 17:30:19 +0900439
440 // nonce
441 byteBuf.writeLong(message.getNonce());
442
443 // Source EID AFI with Source EID address
444 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
445 afiAddressWriter.writeTo(byteBuf, message.getSourceEid());
446
447 // ITR RLOCs
448 List<LispAfiAddress> rlocs = message.getItrRlocs();
449 for (int i = 0; i < rlocs.size(); i++) {
450 afiAddressWriter.writeTo(byteBuf, rlocs.get(i));
451 }
452
453 // EID records
454 EidRecordWriter recordWriter = new EidRecordWriter();
455 List<LispEidRecord> records = message.getEids();
456
457 for (int i = 0; i < records.size(); i++) {
458 recordWriter.writeTo(byteBuf, records.get(i));
459 }
460
461 // TODO: handle Map-Reply record
462 }
463 }
Jian Li451175e2016-07-19 23:22:20 +0900464}