blob: b45d1e60eb7d43e8fe7f49010b2526ea236ab08b [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;
Jian Lie4ba2a42016-08-29 20:24:15 +090032import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordReader;
33import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordWriter;
Jian Li20850d32016-08-04 02:15:57 +090034
Jian Liedc5db12016-08-23 17:30:19 +090035
Jian Li451175e2016-07-19 23:22:20 +090036/**
37 * Default LISP map register message class.
38 */
Jian Lif59c0ad2016-08-02 18:11:30 +090039public final class DefaultLispMapRegister implements LispMapRegister {
40
41 private final long nonce;
42 private final short keyId;
Jian Liedc5db12016-08-23 17:30:19 +090043 private final short authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090044 private final byte[] authenticationData;
Jian Lif59c0ad2016-08-02 18:11:30 +090045 private final List<LispMapRecord> mapRecords;
46 private final boolean proxyMapReply;
47 private final boolean wantMapNotify;
48
49 /**
50 * A private constructor that protects object instantiation from external.
51 *
52 * @param nonce nonce
53 * @param keyId key identifier
Jian Li27759352016-10-04 20:14:42 +090054 * @param authDataLength authentication data length
Jian Lif59c0ad2016-08-02 18:11:30 +090055 * @param authenticationData authentication data
Jian Lif59c0ad2016-08-02 18:11:30 +090056 * @param mapRecords a collection of map records
57 * @param proxyMapReply proxy map reply flag
58 * @param wantMapNotify want map notify flag
59 */
Jian Liedc5db12016-08-23 17:30:19 +090060 private DefaultLispMapRegister(long nonce, short keyId, short authDataLength,
Jian Li42b3e432016-08-31 01:05:20 +090061 byte[] authenticationData, List<LispMapRecord> mapRecords,
Jian Lif59c0ad2016-08-02 18:11:30 +090062 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;
Jian Lif59c0ad2016-08-02 18:11:30 +090067 this.mapRecords = mapRecords;
68 this.proxyMapReply = proxyMapReply;
69 this.wantMapNotify = wantMapNotify;
70 }
71
Jian Li451175e2016-07-19 23:22:20 +090072 @Override
73 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090074 return LispType.LISP_MAP_REGISTER;
Jian Li451175e2016-07-19 23:22:20 +090075 }
76
77 @Override
78 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090079 // TODO: serialize LispMapRegister message
Jian Li451175e2016-07-19 23:22:20 +090080 }
81
82 @Override
83 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090084 return new DefaultRegisterBuilder();
Jian Li451175e2016-07-19 23:22:20 +090085 }
Jian Li719b3bf2016-07-22 00:38:29 +090086
87 @Override
88 public boolean isProxyMapReply() {
Jian Lif59c0ad2016-08-02 18:11:30 +090089 return proxyMapReply;
Jian Li719b3bf2016-07-22 00:38:29 +090090 }
91
92 @Override
93 public boolean isWantMapNotify() {
Jian Lif59c0ad2016-08-02 18:11:30 +090094 return wantMapNotify;
Jian Li719b3bf2016-07-22 00:38:29 +090095 }
96
97 @Override
Jian Li42b3e432016-08-31 01:05:20 +090098 public int getRecordCount() {
99 return mapRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +0900100 }
101
102 @Override
103 public long getNonce() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900104 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900105 }
106
107 @Override
108 public short getKeyId() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900109 return keyId;
Jian Li719b3bf2016-07-22 00:38:29 +0900110 }
111
112 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900113 public short getAuthDataLength() {
114 return authDataLength;
115 }
116
117 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900118 public byte[] getAuthenticationData() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900119 if (authenticationData != null && authenticationData.length != 0) {
120 return ImmutableByteSequence.copyFrom(authenticationData).asArray();
121 } else {
122 return new byte[0];
123 }
Jian Li719b3bf2016-07-22 00:38:29 +0900124 }
125
126 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900127 public List<LispMapRecord> getMapRecords() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900128 return ImmutableList.copyOf(mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900129 }
130
Jian Li20850d32016-08-04 02:15:57 +0900131 @Override
132 public String toString() {
133 return toStringHelper(this)
134 .add("type", getType())
135 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900136 .add("keyId", keyId)
Jian Liedc5db12016-08-23 17:30:19 +0900137 .add("authentication data length", authDataLength)
138 .add("authentication data", authenticationData)
Jian Li20850d32016-08-04 02:15:57 +0900139 .add("mapRecords", mapRecords)
140 .add("proxyMapReply", proxyMapReply)
141 .add("wantMapNotify", wantMapNotify).toString();
142 }
143
144 @Override
145 public boolean equals(Object o) {
146 if (this == o) {
147 return true;
148 }
149 if (o == null || getClass() != o.getClass()) {
150 return false;
151 }
152
153 DefaultLispMapRegister that = (DefaultLispMapRegister) o;
154 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900155 Objects.equal(keyId, that.keyId) &&
Jian Liedc5db12016-08-23 17:30:19 +0900156 Objects.equal(authDataLength, that.authDataLength) &&
Jian Lie4ba2a42016-08-29 20:24:15 +0900157 Arrays.equals(authenticationData, that.authenticationData) &&
Jian Li20850d32016-08-04 02:15:57 +0900158 Objects.equal(proxyMapReply, that.proxyMapReply) &&
159 Objects.equal(wantMapNotify, that.wantMapNotify);
160 }
161
162 @Override
163 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900164 return Objects.hashCode(nonce, keyId, authDataLength,
Jian Lie4ba2a42016-08-29 20:24:15 +0900165 proxyMapReply, wantMapNotify) + Arrays.hashCode(authenticationData);
Jian Li20850d32016-08-04 02:15:57 +0900166 }
167
Jian Li719b3bf2016-07-22 00:38:29 +0900168 public static final class DefaultRegisterBuilder implements RegisterBuilder {
169
Jian Lif59c0ad2016-08-02 18:11:30 +0900170 private long nonce;
171 private short keyId;
Jian Liedc5db12016-08-23 17:30:19 +0900172 private short authDataLength;
Jian Lid4e63702016-08-30 18:29:20 +0900173 private byte[] authenticationData = new byte[0];
Jian Lid4e63702016-08-30 18:29:20 +0900174 private List<LispMapRecord> mapRecords = Lists.newArrayList();
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
Jian Li719b3bf2016-07-22 00:38:29 +0900196 public RegisterBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900197 this.nonce = nonce;
198 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900199 }
200
201 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900202 public RegisterBuilder withAuthDataLength(short authDataLength) {
203 this.authDataLength = authDataLength;
204 return this;
205 }
206
207 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900208 public RegisterBuilder withKeyId(short keyId) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900209 this.keyId = keyId;
210 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900211 }
212
213 @Override
214 public RegisterBuilder withAuthenticationData(byte[] authenticationData) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900215 if (authenticationData != null) {
216 this.authenticationData = authenticationData;
Jian Lie4ba2a42016-08-29 20:24:15 +0900217 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900218 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900219 }
220
221 @Override
Jian Li47671902016-08-11 01:18:18 +0900222 public RegisterBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900223 if (mapRecords != null) {
224 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900225 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900226 return this;
227 }
228
229 @Override
Jian Li525fded2016-08-04 01:15:33 +0900230 public LispMapRegister build() {
Jian Liedc5db12016-08-23 17:30:19 +0900231 return new DefaultLispMapRegister(nonce, keyId, authDataLength,
Jian Li42b3e432016-08-31 01:05:20 +0900232 authenticationData, mapRecords, proxyMapReply, wantMapNotify);
Jian Li719b3bf2016-07-22 00:38:29 +0900233 }
234 }
Jian Li26069e22016-08-10 22:00:52 +0900235
236 /**
Jian Liedc5db12016-08-23 17:30:19 +0900237 * A LISP message reader for MapRegister message.
Jian Li26069e22016-08-10 22:00:52 +0900238 */
Jian Liedc5db12016-08-23 17:30:19 +0900239 public static final class RegisterReader implements LispMessageReader<LispMapRegister> {
Jian Li26069e22016-08-10 22:00:52 +0900240
Jian Li47671902016-08-11 01:18:18 +0900241 private static final int PROXY_MAP_REPLY_INDEX = 3;
242 private static final int WANT_MAP_NOTIFY_INDEX = 0;
243 private static final int RESERVED_SKIP_LENGTH = 1;
244
Jian Li26069e22016-08-10 22:00:52 +0900245 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900246 public LispMapRegister readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900247
248 if (byteBuf.readerIndex() != 0) {
249 return null;
250 }
251
252 // proxyMapReply -> 1 bit
253 boolean proxyMapReplyFlag = ByteOperator.getBit(byteBuf.readByte(), PROXY_MAP_REPLY_INDEX);
254
255 // let's skip the reserved field
256 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
257
258 byte reservedWithFlag = byteBuf.readByte();
259
260 // wantMapReply -> 1 bit
261 boolean wantMapNotifyFlag = ByteOperator.getBit(reservedWithFlag, WANT_MAP_NOTIFY_INDEX);
262
263 // record count -> 8 bits
264 byte recordCount = (byte) byteBuf.readUnsignedByte();
265
266 // nonce -> 64 bits
267 long nonce = byteBuf.readLong();
268
269 // keyId -> 16 bits
270 short keyId = byteBuf.readShort();
271
272 // authenticationDataLength -> 16 bits
273 short authLength = byteBuf.readShort();
274
275 // authenticationData -> depends on the authenticationDataLength
276 byte[] authData = new byte[authLength];
277 byteBuf.readBytes(authData);
278
279 List<LispMapRecord> mapRecords = Lists.newArrayList();
280 for (int i = 0; i < recordCount; i++) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900281 mapRecords.add(new MapRecordReader().readFrom(byteBuf));
Jian Li47671902016-08-11 01:18:18 +0900282 }
283
284 return new DefaultRegisterBuilder()
285 .withIsProxyMapReply(proxyMapReplyFlag)
286 .withIsWantMapNotify(wantMapNotifyFlag)
Jian Li47671902016-08-11 01:18:18 +0900287 .withNonce(nonce)
288 .withKeyId(keyId)
289 .withAuthenticationData(authData)
290 .withMapRecords(mapRecords)
291 .build();
Jian Li26069e22016-08-10 22:00:52 +0900292 }
293 }
Jian Liedc5db12016-08-23 17:30:19 +0900294
295 /**
296 * LISP map register message writer class.
297 */
298 public static class RegisterWriter implements LispMessageWriter<LispMapRegister> {
299
Jian Liedc5db12016-08-23 17:30:19 +0900300 private static final int REGISTER_SHIFT_BIT = 4;
301
302 private static final int PROXY_MAP_REPLY_SHIFT_BIT = 3;
303
304 private static final int ENABLE_BIT = 1;
305 private static final int DISABLE_BIT = 0;
306
307 private static final int UNUSED_ZERO = 0;
308
309 @Override
310 public void writeTo(ByteBuf byteBuf, LispMapRegister message) throws LispWriterException {
311
312 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900313 byte msgType = (byte) (LispType.LISP_MAP_REGISTER.getTypeCode() << REGISTER_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900314
315 // proxy map reply flag
316 byte proxyMapReply = DISABLE_BIT;
317 if (message.isProxyMapReply()) {
318 proxyMapReply = (byte) (ENABLE_BIT << PROXY_MAP_REPLY_SHIFT_BIT);
319 }
320
321 byteBuf.writeByte(msgType + proxyMapReply);
322
323 // fill zero into reserved field
324 byteBuf.writeByte((short) UNUSED_ZERO);
325
326 // want map notify flag
327 byte wantMapNotify = DISABLE_BIT;
328 if (message.isWantMapNotify()) {
329 wantMapNotify = (byte) ENABLE_BIT;
330 }
331
332 byteBuf.writeByte(wantMapNotify);
333
334 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900335 byteBuf.writeByte(message.getMapRecords().size());
Jian Liedc5db12016-08-23 17:30:19 +0900336
337 // nonce
338 byteBuf.writeLong(message.getNonce());
339
340 // keyId
341 byteBuf.writeShort(message.getKeyId());
342
Jian Lif8c2d4a2016-09-15 02:33:12 +0900343 // authentication data and its length
344 if (message.getAuthenticationData() == null) {
345 byteBuf.writeShort((short) 0);
346 } else {
347 byteBuf.writeShort(message.getAuthenticationData().length);
348 byteBuf.writeBytes(message.getAuthenticationData());
Jian Liedc5db12016-08-23 17:30:19 +0900349 }
350
Jian Liedc5db12016-08-23 17:30:19 +0900351 // serialize map records
Jian Lie4ba2a42016-08-29 20:24:15 +0900352 MapRecordWriter writer = new MapRecordWriter();
Jian Liedc5db12016-08-23 17:30:19 +0900353 List<LispMapRecord> records = message.getMapRecords();
354
355 for (int i = 0; i < records.size(); i++) {
356 writer.writeTo(byteBuf, records.get(i));
357 }
358 }
359 }
Jian Li451175e2016-07-19 23:22:20 +0900360}