blob: 75f73b51321b84534d6d1737e423edae1584ca12 [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;
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
52 /**
53 * A private constructor that protects object instantiation from external.
54 *
55 * @param nonce nonce
Jian Lif59c0ad2016-08-02 18:11:30 +090056 * @param sourceEid source EID address
57 * @param itrRlocs a collection of ITR RLOCs
58 * @param eidRecords a collection of EID records
59 * @param authoritative authoritative flag
60 * @param mapDataPresent map data present flag
61 * @param probe probe flag
62 * @param smr smr flag
63 * @param pitr pitr flag
64 * @param smrInvoked smrInvoked flag
65 */
Jian Li42b3e432016-08-31 01:05:20 +090066 private DefaultLispMapRequest(long nonce, LispAfiAddress sourceEid,
Jian Lif59c0ad2016-08-02 18:11:30 +090067 List<LispAfiAddress> itrRlocs, List<LispEidRecord> eidRecords,
68 boolean authoritative, boolean mapDataPresent, boolean probe,
69 boolean smr, boolean pitr, boolean smrInvoked) {
70 this.nonce = nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090071 this.sourceEid = sourceEid;
72 this.itrRlocs = itrRlocs;
73 this.eidRecords = eidRecords;
74 this.authoritative = authoritative;
75 this.mapDataPresent = mapDataPresent;
76 this.probe = probe;
77 this.smr = smr;
78 this.pitr = pitr;
79 this.smrInvoked = smrInvoked;
80 }
81
Jian Li451175e2016-07-19 23:22:20 +090082 @Override
83 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090084 return LispType.LISP_MAP_REQUEST;
Jian Li451175e2016-07-19 23:22:20 +090085 }
86
87 @Override
88 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090089 // TODO: serialize LispMapRequest message
Jian Li451175e2016-07-19 23:22:20 +090090 }
91
92 @Override
93 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090094 return new DefaultRequestBuilder();
Jian Li451175e2016-07-19 23:22:20 +090095 }
Jian Li719b3bf2016-07-22 00:38:29 +090096
97 @Override
98 public boolean isAuthoritative() {
Jian Liedc5db12016-08-23 17:30:19 +090099 return authoritative;
Jian Lif59c0ad2016-08-02 18:11:30 +0900100 }
101
102 @Override
103 public boolean isMapDataPresent() {
Jian Liedc5db12016-08-23 17:30:19 +0900104 return mapDataPresent;
Jian Li719b3bf2016-07-22 00:38:29 +0900105 }
106
107 @Override
108 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +0900109 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +0900110 }
111
112 @Override
113 public boolean isSmr() {
Jian Liedc5db12016-08-23 17:30:19 +0900114 return smr;
Jian Li719b3bf2016-07-22 00:38:29 +0900115 }
116
117 @Override
118 public boolean isPitr() {
Jian Liedc5db12016-08-23 17:30:19 +0900119 return pitr;
Jian Li719b3bf2016-07-22 00:38:29 +0900120 }
121
122 @Override
123 public boolean isSmrInvoked() {
Jian Liedc5db12016-08-23 17:30:19 +0900124 return smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900125 }
126
127 @Override
Jian Li42b3e432016-08-31 01:05:20 +0900128 public int getRecordCount() {
129 return eidRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +0900130 }
131
132 @Override
133 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +0900134 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900135 }
136
137 @Override
138 public LispAfiAddress getSourceEid() {
Jian Liedc5db12016-08-23 17:30:19 +0900139 return sourceEid;
Jian Li719b3bf2016-07-22 00:38:29 +0900140 }
141
142 @Override
143 public List<LispAfiAddress> getItrRlocs() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900144 return ImmutableList.copyOf(itrRlocs);
Jian Li719b3bf2016-07-22 00:38:29 +0900145 }
146
147 @Override
Jian Li10a09062016-07-26 23:58:50 +0900148 public List<LispEidRecord> getEids() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900149 return ImmutableList.copyOf(eidRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900150 }
151
Jian Li20850d32016-08-04 02:15:57 +0900152 @Override
153 public String toString() {
154 return toStringHelper(this)
155 .add("type", getType())
156 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900157 .add("source EID", sourceEid)
158 .add("ITR rlocs", itrRlocs)
159 .add("EID records", eidRecords)
160 .add("authoritative", authoritative)
161 .add("mapDataPresent", mapDataPresent)
162 .add("probe", probe)
163 .add("SMR", smr)
164 .add("Proxy ITR", pitr)
165 .add("SMR Invoked", smrInvoked).toString();
166 }
167
168 @Override
169 public boolean equals(Object o) {
170 if (this == o) {
171 return true;
172 }
173 if (o == null || getClass() != o.getClass()) {
174 return false;
175 }
176 DefaultLispMapRequest that = (DefaultLispMapRequest) o;
177 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900178 Objects.equal(sourceEid, that.sourceEid) &&
Jian Li20850d32016-08-04 02:15:57 +0900179 Objects.equal(authoritative, that.authoritative) &&
180 Objects.equal(mapDataPresent, that.mapDataPresent) &&
181 Objects.equal(probe, that.probe) &&
182 Objects.equal(smr, that.smr) &&
183 Objects.equal(pitr, that.pitr) &&
184 Objects.equal(smrInvoked, that.smrInvoked);
185 }
186
187 @Override
188 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900189 return Objects.hashCode(nonce, sourceEid, authoritative,
Jian Lie4ba2a42016-08-29 20:24:15 +0900190 mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li20850d32016-08-04 02:15:57 +0900191 }
192
Jian Li719b3bf2016-07-22 00:38:29 +0900193 public static final class DefaultRequestBuilder implements RequestBuilder {
194
Jian Lif59c0ad2016-08-02 18:11:30 +0900195 private long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +0900196 private LispAfiAddress sourceEid;
197 private List<LispAfiAddress> itrRlocs = Lists.newArrayList();
198 private List<LispEidRecord> eidRecords = Lists.newArrayList();
199 private boolean authoritative;
200 private boolean mapDataPresent;
201 private boolean probe;
202 private boolean smr;
203 private boolean pitr;
204 private boolean smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900205
206 @Override
207 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900208 return LispType.LISP_MAP_REQUEST;
Jian Li719b3bf2016-07-22 00:38:29 +0900209 }
210
211 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900212 public RequestBuilder withIsAuthoritative(boolean authoritative) {
213 this.authoritative = authoritative;
214 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900215 }
216
217 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900218 public RequestBuilder withIsProbe(boolean probe) {
219 this.probe = probe;
220 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900221 }
222
223 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900224 public RequestBuilder withIsMapDataPresent(boolean mapDataPresent) {
225 this.mapDataPresent = mapDataPresent;
226 return this;
227 }
228
Jian Lif59c0ad2016-08-02 18:11:30 +0900229 @Override
230 public RequestBuilder withIsSmr(boolean smr) {
231 this.smr = smr;
232 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900233 }
234
235 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900236 public RequestBuilder withIsPitr(boolean pitr) {
237 this.pitr = pitr;
238 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900239 }
240
241 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900242 public RequestBuilder withIsSmrInvoked(boolean smrInvoked) {
243 this.smrInvoked = smrInvoked;
244 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900245 }
246
247 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900248 public RequestBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900249 this.nonce = nonce;
250 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900251 }
252
253 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900254 public RequestBuilder withSourceEid(LispAfiAddress sourceEid) {
255 this.sourceEid = sourceEid;
256 return this;
257 }
258
259 @Override
Jian Li47671902016-08-11 01:18:18 +0900260 public RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900261 if (itrRlocs != null) {
262 this.itrRlocs = ImmutableList.copyOf(itrRlocs);
Jian Lie4ba2a42016-08-29 20:24:15 +0900263 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900264 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900265 }
266
267 @Override
Jian Li47671902016-08-11 01:18:18 +0900268 public RequestBuilder withEidRecords(List<LispEidRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900269 if (records != null) {
270 this.eidRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900271 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900272 return this;
273 }
274
275 @Override
Jian Li525fded2016-08-04 01:15:33 +0900276 public LispMapRequest build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900277
278 checkNotNull(sourceEid, "Must have a source EID");
279 checkArgument((itrRlocs != null) && (itrRlocs.size() > 0), "Must have an ITR RLOC entry");
280
Jian Li42b3e432016-08-31 01:05:20 +0900281 return new DefaultLispMapRequest(nonce, sourceEid, itrRlocs, eidRecords,
282 authoritative, mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li719b3bf2016-07-22 00:38:29 +0900283 }
284 }
Jian Li26069e22016-08-10 22:00:52 +0900285
286 /**
Jian Liedc5db12016-08-23 17:30:19 +0900287 * A LISP message reader for MapRequest message.
Jian Li26069e22016-08-10 22:00:52 +0900288 */
Jian Liedc5db12016-08-23 17:30:19 +0900289 public static final class RequestReader implements LispMessageReader<LispMapRequest> {
Jian Li26069e22016-08-10 22:00:52 +0900290
Jian Li47671902016-08-11 01:18:18 +0900291 private static final int AUTHORITATIVE_INDEX = 3;
292 private static final int MAP_DATA_PRESENT_INDEX = 2;
293 private static final int PROBE_INDEX = 1;
294 private static final int SMR_INDEX = 0;
295 private static final int PITR_INDEX = 7;
296 private static final int SMR_INVOKED_INDEX = 6;
297
Jian Li26069e22016-08-10 22:00:52 +0900298 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900299 public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900300
301 if (byteBuf.readerIndex() != 0) {
302 return null;
303 }
304
305 byte typeWithFlags = byteBuf.readByte();
306
307 // authoritative -> 1 bit
308 boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);
309
310 // mapDataPresent -> 1 bit
311 boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);
312
313 // probe -> 1 bit
314 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
315
316 // smr -> 1 bit
317 boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);
318
319 byte reservedWithFlags = byteBuf.readByte();
320
321 // pitr -> 1 bit
322 boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);
323
324 // smrInvoked -> 1 bit
325 boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);
326
327 // let's skip reserved field, only obtains ITR counter value
328 // assume that first 3 bits are all set as 0,
329 // remain 5 bits represent Itr Rloc Counter (IRC)
Jian Lie4ba2a42016-08-29 20:24:15 +0900330 int irc = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900331
332 // record count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900333 int recordCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900334
335 // nonce -> 64 bits
336 long nonce = byteBuf.readLong();
337
Jian Lia7b394d2016-08-21 23:11:46 +0900338 LispAfiAddress sourceEid = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900339
Jian Lia7b394d2016-08-21 23:11:46 +0900340 // deserialize a collection of RLOC addresses
341 List<LispAfiAddress> itrRlocs = Lists.newArrayList();
342 for (int i = 0; i < irc; i++) {
343 itrRlocs.add(new LispAfiAddress.AfiAddressReader().readFrom(byteBuf));
344 }
Jian Li47671902016-08-11 01:18:18 +0900345
Jian Lia7b394d2016-08-21 23:11:46 +0900346 // deserialize a collection of EID records
347 List<LispEidRecord> eidRecords = Lists.newArrayList();
348 for (int i = 0; i < recordCount; i++) {
349 eidRecords.add(new LispEidRecord.EidRecordReader().readFrom(byteBuf));
350 }
Jian Li47671902016-08-11 01:18:18 +0900351
352 return new DefaultRequestBuilder()
353 .withIsAuthoritative(authoritative)
354 .withIsMapDataPresent(mapDataPresent)
355 .withIsProbe(probe)
356 .withIsSmr(smr)
357 .withIsPitr(pitr)
358 .withIsSmrInvoked(smrInvoked)
359 .withNonce(nonce)
Jian Lia7b394d2016-08-21 23:11:46 +0900360 .withSourceEid(sourceEid)
361 .withEidRecords(eidRecords)
362 .withItrRlocs(itrRlocs)
Jian Li47671902016-08-11 01:18:18 +0900363 .build();
Jian Li26069e22016-08-10 22:00:52 +0900364 }
365 }
Jian Liedc5db12016-08-23 17:30:19 +0900366
367 /**
368 * A LISP message writer for MapRequest message.
369 */
370 public static final class RequestWriter implements LispMessageWriter<LispMapRequest> {
371
Jian Liedc5db12016-08-23 17:30:19 +0900372 private static final int REQUEST_SHIFT_BIT = 4;
373
374 private static final int AUTHORITATIVE_SHIFT_BIT = 3;
375 private static final int MAP_DATA_PRESENT_SHIFT_BIT = 2;
376 private static final int PROBE_SHIFT_BIT = 1;
377
378 private static final int PITR_SHIFT_BIT = 7;
379 private static final int SMR_INVOKED_SHIFT_BIT = 6;
380
381 private static final int ENABLE_BIT = 1;
382 private static final int DISABLE_BIT = 0;
383
Jian Liedc5db12016-08-23 17:30:19 +0900384 @Override
385 public void writeTo(ByteBuf byteBuf, LispMapRequest message) throws LispWriterException {
386
387 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900388 byte msgType = (byte) (LispType.LISP_MAP_REQUEST.getTypeCode() << REQUEST_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900389
390 // authoritative flag
391 byte authoritative = DISABLE_BIT;
392 if (message.isAuthoritative()) {
393 authoritative = (byte) (ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT);
394 }
395
396 // map data present flag
397 byte mapDataPresent = DISABLE_BIT;
398 if (message.isMapDataPresent()) {
399 mapDataPresent = (byte) (ENABLE_BIT << MAP_DATA_PRESENT_SHIFT_BIT);
400 }
401
402 // probe flag
403 byte probe = DISABLE_BIT;
404 if (message.isProbe()) {
405 probe = (byte) (ENABLE_BIT << PROBE_SHIFT_BIT);
406 }
407
408 // SMR flag
409 byte smr = DISABLE_BIT;
410 if (message.isSmr()) {
411 smr = (byte) ENABLE_BIT;
412 }
413
414 byteBuf.writeByte((byte) (msgType + authoritative + mapDataPresent + probe + smr));
415
416 // PITR flag bit
417 byte pitr = DISABLE_BIT;
418 if (message.isPitr()) {
419 pitr = (byte) (ENABLE_BIT << PITR_SHIFT_BIT);
420 }
421
422 // SMR invoked flag bit
423 byte smrInvoked = DISABLE_BIT;
424 if (message.isSmrInvoked()) {
425 smrInvoked = (byte) (ENABLE_BIT << SMR_INVOKED_SHIFT_BIT);
426 }
427
428 byteBuf.writeByte((byte) (pitr + smrInvoked));
429
Jian Lie4ba2a42016-08-29 20:24:15 +0900430 // ITR Rloc count
431 byteBuf.writeByte((byte) message.getItrRlocs().size());
Jian Liedc5db12016-08-23 17:30:19 +0900432
433 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900434 byteBuf.writeByte(message.getEids().size());
Jian Liedc5db12016-08-23 17:30:19 +0900435
436 // nonce
437 byteBuf.writeLong(message.getNonce());
438
439 // Source EID AFI with Source EID address
440 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
441 afiAddressWriter.writeTo(byteBuf, message.getSourceEid());
442
443 // ITR RLOCs
444 List<LispAfiAddress> rlocs = message.getItrRlocs();
445 for (int i = 0; i < rlocs.size(); i++) {
446 afiAddressWriter.writeTo(byteBuf, rlocs.get(i));
447 }
448
449 // EID records
450 EidRecordWriter recordWriter = new EidRecordWriter();
451 List<LispEidRecord> records = message.getEids();
452
453 for (int i = 0; i < records.size(); i++) {
454 recordWriter.writeTo(byteBuf, records.get(i));
455 }
456
457 // TODO: handle Map-Reply record
458 }
459 }
Jian Li451175e2016-07-19 23:22:20 +0900460}