blob: abaf3c8968a8422c1aa0794d86d15f4b0430dd9d [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 Lif59c0ad2016-08-02 18:11:30 +090023import org.onlab.util.ImmutableByteSequence;
Jian Li26069e22016-08-10 22:00:52 +090024import org.onosproject.lisp.msg.exceptions.LispParseError;
Jian Lia7b394d2016-08-21 23:11:46 +090025import org.onosproject.lisp.msg.exceptions.LispReaderException;
Jian Liedc5db12016-08-23 17:30:19 +090026import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li451175e2016-07-19 23:22:20 +090027
Jian Liedc5db12016-08-23 17:30:19 +090028import java.util.Arrays;
Jian Li719b3bf2016-07-22 00:38:29 +090029import java.util.List;
30
Jian Li20850d32016-08-04 02:15:57 +090031import static com.google.common.base.MoreObjects.toStringHelper;
32
Jian Liedc5db12016-08-23 17:30:19 +090033
Jian Li451175e2016-07-19 23:22:20 +090034/**
35 * Default LISP map register message class.
36 */
Jian Lif59c0ad2016-08-02 18:11:30 +090037public final class DefaultLispMapRegister implements LispMapRegister {
38
39 private final long nonce;
40 private final short keyId;
Jian Liedc5db12016-08-23 17:30:19 +090041 private final short authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090042 private final byte[] authenticationData;
43 private final byte recordCount;
44 private final List<LispMapRecord> mapRecords;
45 private final boolean proxyMapReply;
46 private final boolean wantMapNotify;
47
48 /**
49 * A private constructor that protects object instantiation from external.
50 *
51 * @param nonce nonce
52 * @param keyId key identifier
53 * @param authenticationData authentication data
54 * @param recordCount record count number
55 * @param mapRecords a collection of map records
56 * @param proxyMapReply proxy map reply flag
57 * @param wantMapNotify want map notify flag
58 */
Jian Liedc5db12016-08-23 17:30:19 +090059 private DefaultLispMapRegister(long nonce, short keyId, short authDataLength,
Jian Lif59c0ad2016-08-02 18:11:30 +090060 byte[] authenticationData, byte recordCount,
61 List<LispMapRecord> mapRecords,
62 boolean proxyMapReply, boolean wantMapNotify) {
63 this.nonce = nonce;
64 this.keyId = keyId;
Jian Liedc5db12016-08-23 17:30:19 +090065 this.authDataLength = authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090066 this.authenticationData = authenticationData;
67 this.recordCount = recordCount;
68 this.mapRecords = mapRecords;
69 this.proxyMapReply = proxyMapReply;
70 this.wantMapNotify = wantMapNotify;
71 }
72
Jian Li451175e2016-07-19 23:22:20 +090073 @Override
74 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090075 return LispType.LISP_MAP_REGISTER;
Jian Li451175e2016-07-19 23:22:20 +090076 }
77
78 @Override
79 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090080 // TODO: serialize LispMapRegister message
Jian Li451175e2016-07-19 23:22:20 +090081 }
82
83 @Override
84 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090085 return new DefaultRegisterBuilder();
Jian Li451175e2016-07-19 23:22:20 +090086 }
Jian Li719b3bf2016-07-22 00:38:29 +090087
88 @Override
89 public boolean isProxyMapReply() {
Jian Lif59c0ad2016-08-02 18:11:30 +090090 return proxyMapReply;
Jian Li719b3bf2016-07-22 00:38:29 +090091 }
92
93 @Override
94 public boolean isWantMapNotify() {
Jian Lif59c0ad2016-08-02 18:11:30 +090095 return wantMapNotify;
Jian Li719b3bf2016-07-22 00:38:29 +090096 }
97
98 @Override
99 public byte getRecordCount() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900100 return recordCount;
Jian Li719b3bf2016-07-22 00:38:29 +0900101 }
102
103 @Override
104 public long getNonce() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900105 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900106 }
107
108 @Override
109 public short getKeyId() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900110 return keyId;
Jian Li719b3bf2016-07-22 00:38:29 +0900111 }
112
113 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900114 public short getAuthDataLength() {
115 return authDataLength;
116 }
117
118 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900119 public byte[] getAuthenticationData() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900120 return ImmutableByteSequence.copyFrom(this.authenticationData).asArray();
Jian Li719b3bf2016-07-22 00:38:29 +0900121 }
122
123 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900124 public List<LispMapRecord> getMapRecords() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900125 return ImmutableList.copyOf(mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900126 }
127
Jian Li20850d32016-08-04 02:15:57 +0900128 @Override
129 public String toString() {
130 return toStringHelper(this)
131 .add("type", getType())
132 .add("nonce", nonce)
133 .add("recordCount", recordCount)
134 .add("keyId", keyId)
Jian Liedc5db12016-08-23 17:30:19 +0900135 .add("authentication data length", authDataLength)
136 .add("authentication data", authenticationData)
Jian Li20850d32016-08-04 02:15:57 +0900137 .add("mapRecords", mapRecords)
138 .add("proxyMapReply", proxyMapReply)
139 .add("wantMapNotify", wantMapNotify).toString();
140 }
141
142 @Override
143 public boolean equals(Object o) {
144 if (this == o) {
145 return true;
146 }
147 if (o == null || getClass() != o.getClass()) {
148 return false;
149 }
150
151 DefaultLispMapRegister that = (DefaultLispMapRegister) o;
152 return Objects.equal(nonce, that.nonce) &&
153 Objects.equal(recordCount, that.recordCount) &&
154 Objects.equal(keyId, that.keyId) &&
Jian Liedc5db12016-08-23 17:30:19 +0900155 Objects.equal(authDataLength, that.authDataLength) &&
Jian Li20850d32016-08-04 02:15:57 +0900156 Objects.equal(authenticationData, that.authenticationData) &&
157 Objects.equal(proxyMapReply, that.proxyMapReply) &&
158 Objects.equal(wantMapNotify, that.wantMapNotify);
159 }
160
161 @Override
162 public int hashCode() {
Jian Liedc5db12016-08-23 17:30:19 +0900163 return Objects.hashCode(nonce, recordCount, keyId, authDataLength,
164 authenticationData, proxyMapReply, wantMapNotify);
Jian Li20850d32016-08-04 02:15:57 +0900165 }
166
Jian Li719b3bf2016-07-22 00:38:29 +0900167 public static final class DefaultRegisterBuilder implements RegisterBuilder {
168
Jian Lif59c0ad2016-08-02 18:11:30 +0900169 private long nonce;
170 private short keyId;
Jian Liedc5db12016-08-23 17:30:19 +0900171 private short authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +0900172 private byte[] authenticationData;
173 private byte recordCount;
Jian Li47671902016-08-11 01:18:18 +0900174 private List<LispMapRecord> mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +0900175 private boolean proxyMapReply;
176 private boolean wantMapNotify;
Jian Li719b3bf2016-07-22 00:38:29 +0900177
178 @Override
179 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900180 return LispType.LISP_MAP_REGISTER;
Jian Li719b3bf2016-07-22 00:38:29 +0900181 }
182
183 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900184 public RegisterBuilder withIsProxyMapReply(boolean proxyMapReply) {
185 this.proxyMapReply = proxyMapReply;
186 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900187 }
188
189 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900190 public RegisterBuilder withIsWantMapNotify(boolean wantMapNotify) {
191 this.wantMapNotify = wantMapNotify;
192 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900193 }
194
195 @Override
196 public RegisterBuilder withRecordCount(byte recordCount) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900197 this.recordCount = recordCount;
198 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900199 }
200
201 @Override
202 public RegisterBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900203 this.nonce = nonce;
204 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900205 }
206
207 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900208 public RegisterBuilder withAuthDataLength(short authDataLength) {
209 this.authDataLength = authDataLength;
210 return this;
211 }
212
213 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900214 public RegisterBuilder withKeyId(short keyId) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900215 this.keyId = keyId;
216 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900217 }
218
219 @Override
220 public RegisterBuilder withAuthenticationData(byte[] authenticationData) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900221 this.authenticationData = authenticationData;
222 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900223 }
224
225 @Override
Jian Li47671902016-08-11 01:18:18 +0900226 public RegisterBuilder withMapRecords(List<LispMapRecord> mapRecords) {
227 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lif59c0ad2016-08-02 18:11:30 +0900228 return this;
229 }
230
231 @Override
Jian Li525fded2016-08-04 01:15:33 +0900232 public LispMapRegister build() {
Jian Liedc5db12016-08-23 17:30:19 +0900233 return new DefaultLispMapRegister(nonce, keyId, authDataLength,
234 authenticationData, recordCount, mapRecords, proxyMapReply, wantMapNotify);
Jian Li719b3bf2016-07-22 00:38:29 +0900235 }
236 }
Jian Li26069e22016-08-10 22:00:52 +0900237
238 /**
Jian Liedc5db12016-08-23 17:30:19 +0900239 * A LISP message reader for MapRegister message.
Jian Li26069e22016-08-10 22:00:52 +0900240 */
Jian Liedc5db12016-08-23 17:30:19 +0900241 public static final class RegisterReader implements LispMessageReader<LispMapRegister> {
Jian Li26069e22016-08-10 22:00:52 +0900242
Jian Li47671902016-08-11 01:18:18 +0900243 private static final int PROXY_MAP_REPLY_INDEX = 3;
244 private static final int WANT_MAP_NOTIFY_INDEX = 0;
245 private static final int RESERVED_SKIP_LENGTH = 1;
246
Jian Li26069e22016-08-10 22:00:52 +0900247 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900248 public LispMapRegister readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900249
250 if (byteBuf.readerIndex() != 0) {
251 return null;
252 }
253
254 // proxyMapReply -> 1 bit
255 boolean proxyMapReplyFlag = ByteOperator.getBit(byteBuf.readByte(), PROXY_MAP_REPLY_INDEX);
256
257 // let's skip the reserved field
258 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
259
260 byte reservedWithFlag = byteBuf.readByte();
261
262 // wantMapReply -> 1 bit
263 boolean wantMapNotifyFlag = ByteOperator.getBit(reservedWithFlag, WANT_MAP_NOTIFY_INDEX);
264
265 // record count -> 8 bits
266 byte recordCount = (byte) byteBuf.readUnsignedByte();
267
268 // nonce -> 64 bits
269 long nonce = byteBuf.readLong();
270
271 // keyId -> 16 bits
272 short keyId = byteBuf.readShort();
273
274 // authenticationDataLength -> 16 bits
275 short authLength = byteBuf.readShort();
276
277 // authenticationData -> depends on the authenticationDataLength
278 byte[] authData = new byte[authLength];
279 byteBuf.readBytes(authData);
280
281 List<LispMapRecord> mapRecords = Lists.newArrayList();
282 for (int i = 0; i < recordCount; i++) {
283 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
284 }
285
286 return new DefaultRegisterBuilder()
287 .withIsProxyMapReply(proxyMapReplyFlag)
288 .withIsWantMapNotify(wantMapNotifyFlag)
289 .withRecordCount(recordCount)
290 .withNonce(nonce)
291 .withKeyId(keyId)
292 .withAuthenticationData(authData)
293 .withMapRecords(mapRecords)
294 .build();
Jian Li26069e22016-08-10 22:00:52 +0900295 }
296 }
Jian Liedc5db12016-08-23 17:30:19 +0900297
298 /**
299 * LISP map register message writer class.
300 */
301 public static class RegisterWriter implements LispMessageWriter<LispMapRegister> {
302
303 private static final int REGISTER_MSG_TYPE = 3;
304 private static final int REGISTER_SHIFT_BIT = 4;
305
306 private static final int PROXY_MAP_REPLY_SHIFT_BIT = 3;
307
308 private static final int ENABLE_BIT = 1;
309 private static final int DISABLE_BIT = 0;
310
311 private static final int UNUSED_ZERO = 0;
312
313 @Override
314 public void writeTo(ByteBuf byteBuf, LispMapRegister message) throws LispWriterException {
315
316 // specify LISP message type
317 byte msgType = (byte) (REGISTER_MSG_TYPE << REGISTER_SHIFT_BIT);
318
319 // proxy map reply flag
320 byte proxyMapReply = DISABLE_BIT;
321 if (message.isProxyMapReply()) {
322 proxyMapReply = (byte) (ENABLE_BIT << PROXY_MAP_REPLY_SHIFT_BIT);
323 }
324
325 byteBuf.writeByte(msgType + proxyMapReply);
326
327 // fill zero into reserved field
328 byteBuf.writeByte((short) UNUSED_ZERO);
329
330 // want map notify flag
331 byte wantMapNotify = DISABLE_BIT;
332 if (message.isWantMapNotify()) {
333 wantMapNotify = (byte) ENABLE_BIT;
334 }
335
336 byteBuf.writeByte(wantMapNotify);
337
338 // record count
339 byteBuf.writeByte(message.getRecordCount());
340
341 // nonce
342 byteBuf.writeLong(message.getNonce());
343
344 // keyId
345 byteBuf.writeShort(message.getKeyId());
346
347 // authentication data length in octet
348 byteBuf.writeShort(message.getAuthDataLength());
349
350 // authentication data
351 byte[] data = message.getAuthenticationData();
352 byte[] clone;
353 if (data != null) {
354 clone = data.clone();
355 Arrays.fill(clone, (byte) UNUSED_ZERO);
356 }
357
358 byteBuf.writeBytes(data);
359
360 // TODO: need to implement MAC authentication mechanism
361
362 // serialize map records
363 DefaultLispMapRecord.MapRecordWriter writer = new DefaultLispMapRecord.MapRecordWriter();
364 List<LispMapRecord> records = message.getMapRecords();
365
366 for (int i = 0; i < records.size(); i++) {
367 writer.writeTo(byteBuf, records.get(i));
368 }
369 }
370 }
Jian Li451175e2016-07-19 23:22:20 +0900371}