blob: 7ccc7b676aaa1ed5120fabc8cbd281278fe94cc1 [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
54 * @param authenticationData authentication data
Jian Lif59c0ad2016-08-02 18:11:30 +090055 * @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 Li42b3e432016-08-31 01:05:20 +090060 byte[] authenticationData, List<LispMapRecord> mapRecords,
Jian Lif59c0ad2016-08-02 18:11:30 +090061 boolean proxyMapReply, boolean wantMapNotify) {
62 this.nonce = nonce;
63 this.keyId = keyId;
Jian Liedc5db12016-08-23 17:30:19 +090064 this.authDataLength = authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090065 this.authenticationData = authenticationData;
Jian Lif59c0ad2016-08-02 18:11:30 +090066 this.mapRecords = mapRecords;
67 this.proxyMapReply = proxyMapReply;
68 this.wantMapNotify = wantMapNotify;
69 }
70
Jian Li451175e2016-07-19 23:22:20 +090071 @Override
72 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090073 return LispType.LISP_MAP_REGISTER;
Jian Li451175e2016-07-19 23:22:20 +090074 }
75
76 @Override
77 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090078 // TODO: serialize LispMapRegister message
Jian Li451175e2016-07-19 23:22:20 +090079 }
80
81 @Override
82 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090083 return new DefaultRegisterBuilder();
Jian Li451175e2016-07-19 23:22:20 +090084 }
Jian Li719b3bf2016-07-22 00:38:29 +090085
86 @Override
87 public boolean isProxyMapReply() {
Jian Lif59c0ad2016-08-02 18:11:30 +090088 return proxyMapReply;
Jian Li719b3bf2016-07-22 00:38:29 +090089 }
90
91 @Override
92 public boolean isWantMapNotify() {
Jian Lif59c0ad2016-08-02 18:11:30 +090093 return wantMapNotify;
Jian Li719b3bf2016-07-22 00:38:29 +090094 }
95
96 @Override
Jian Li42b3e432016-08-31 01:05:20 +090097 public int getRecordCount() {
98 return mapRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +090099 }
100
101 @Override
102 public long getNonce() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900103 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900104 }
105
106 @Override
107 public short getKeyId() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900108 return keyId;
Jian Li719b3bf2016-07-22 00:38:29 +0900109 }
110
111 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900112 public short getAuthDataLength() {
113 return authDataLength;
114 }
115
116 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900117 public byte[] getAuthenticationData() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900118 if (authenticationData != null && authenticationData.length != 0) {
119 return ImmutableByteSequence.copyFrom(authenticationData).asArray();
120 } else {
121 return new byte[0];
122 }
Jian Li719b3bf2016-07-22 00:38:29 +0900123 }
124
125 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900126 public List<LispMapRecord> getMapRecords() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900127 return ImmutableList.copyOf(mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900128 }
129
Jian Li20850d32016-08-04 02:15:57 +0900130 @Override
131 public String toString() {
132 return toStringHelper(this)
133 .add("type", getType())
134 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900135 .add("keyId", keyId)
Jian Liedc5db12016-08-23 17:30:19 +0900136 .add("authentication data length", authDataLength)
137 .add("authentication data", authenticationData)
Jian Li20850d32016-08-04 02:15:57 +0900138 .add("mapRecords", mapRecords)
139 .add("proxyMapReply", proxyMapReply)
140 .add("wantMapNotify", wantMapNotify).toString();
141 }
142
143 @Override
144 public boolean equals(Object o) {
145 if (this == o) {
146 return true;
147 }
148 if (o == null || getClass() != o.getClass()) {
149 return false;
150 }
151
152 DefaultLispMapRegister that = (DefaultLispMapRegister) o;
153 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900154 Objects.equal(keyId, that.keyId) &&
Jian Liedc5db12016-08-23 17:30:19 +0900155 Objects.equal(authDataLength, that.authDataLength) &&
Jian Lie4ba2a42016-08-29 20:24:15 +0900156 Arrays.equals(authenticationData, that.authenticationData) &&
Jian Li20850d32016-08-04 02:15:57 +0900157 Objects.equal(proxyMapReply, that.proxyMapReply) &&
158 Objects.equal(wantMapNotify, that.wantMapNotify);
159 }
160
161 @Override
162 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900163 return Objects.hashCode(nonce, keyId, authDataLength,
Jian Lie4ba2a42016-08-29 20:24:15 +0900164 proxyMapReply, wantMapNotify) + Arrays.hashCode(authenticationData);
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 Lid4e63702016-08-30 18:29:20 +0900172 private byte[] authenticationData = new byte[0];
Jian Lid4e63702016-08-30 18:29:20 +0900173 private List<LispMapRecord> mapRecords = Lists.newArrayList();
Jian Lif59c0ad2016-08-02 18:11:30 +0900174 private boolean proxyMapReply;
175 private boolean wantMapNotify;
Jian Li719b3bf2016-07-22 00:38:29 +0900176
177 @Override
178 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900179 return LispType.LISP_MAP_REGISTER;
Jian Li719b3bf2016-07-22 00:38:29 +0900180 }
181
182 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900183 public RegisterBuilder withIsProxyMapReply(boolean proxyMapReply) {
184 this.proxyMapReply = proxyMapReply;
185 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900186 }
187
188 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900189 public RegisterBuilder withIsWantMapNotify(boolean wantMapNotify) {
190 this.wantMapNotify = wantMapNotify;
191 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900192 }
193
194 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900195 public RegisterBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900196 this.nonce = nonce;
197 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900198 }
199
200 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900201 public RegisterBuilder withAuthDataLength(short authDataLength) {
202 this.authDataLength = authDataLength;
203 return this;
204 }
205
206 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900207 public RegisterBuilder withKeyId(short keyId) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900208 this.keyId = keyId;
209 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900210 }
211
212 @Override
213 public RegisterBuilder withAuthenticationData(byte[] authenticationData) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900214 if (authenticationData != null) {
215 this.authenticationData = authenticationData;
Jian Lie4ba2a42016-08-29 20:24:15 +0900216 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900217 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900218 }
219
220 @Override
Jian Li47671902016-08-11 01:18:18 +0900221 public RegisterBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900222 if (mapRecords != null) {
223 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900224 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900225 return this;
226 }
227
228 @Override
Jian Li525fded2016-08-04 01:15:33 +0900229 public LispMapRegister build() {
Jian Liedc5db12016-08-23 17:30:19 +0900230 return new DefaultLispMapRegister(nonce, keyId, authDataLength,
Jian Li42b3e432016-08-31 01:05:20 +0900231 authenticationData, mapRecords, proxyMapReply, wantMapNotify);
Jian Li719b3bf2016-07-22 00:38:29 +0900232 }
233 }
Jian Li26069e22016-08-10 22:00:52 +0900234
235 /**
Jian Liedc5db12016-08-23 17:30:19 +0900236 * A LISP message reader for MapRegister message.
Jian Li26069e22016-08-10 22:00:52 +0900237 */
Jian Liedc5db12016-08-23 17:30:19 +0900238 public static final class RegisterReader implements LispMessageReader<LispMapRegister> {
Jian Li26069e22016-08-10 22:00:52 +0900239
Jian Li47671902016-08-11 01:18:18 +0900240 private static final int PROXY_MAP_REPLY_INDEX = 3;
241 private static final int WANT_MAP_NOTIFY_INDEX = 0;
242 private static final int RESERVED_SKIP_LENGTH = 1;
243
Jian Li26069e22016-08-10 22:00:52 +0900244 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900245 public LispMapRegister readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900246
247 if (byteBuf.readerIndex() != 0) {
248 return null;
249 }
250
251 // proxyMapReply -> 1 bit
252 boolean proxyMapReplyFlag = ByteOperator.getBit(byteBuf.readByte(), PROXY_MAP_REPLY_INDEX);
253
254 // let's skip the reserved field
255 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
256
257 byte reservedWithFlag = byteBuf.readByte();
258
259 // wantMapReply -> 1 bit
260 boolean wantMapNotifyFlag = ByteOperator.getBit(reservedWithFlag, WANT_MAP_NOTIFY_INDEX);
261
262 // record count -> 8 bits
263 byte recordCount = (byte) byteBuf.readUnsignedByte();
264
265 // nonce -> 64 bits
266 long nonce = byteBuf.readLong();
267
268 // keyId -> 16 bits
269 short keyId = byteBuf.readShort();
270
271 // authenticationDataLength -> 16 bits
272 short authLength = byteBuf.readShort();
273
274 // authenticationData -> depends on the authenticationDataLength
275 byte[] authData = new byte[authLength];
276 byteBuf.readBytes(authData);
277
278 List<LispMapRecord> mapRecords = Lists.newArrayList();
279 for (int i = 0; i < recordCount; i++) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900280 mapRecords.add(new MapRecordReader().readFrom(byteBuf));
Jian Li47671902016-08-11 01:18:18 +0900281 }
282
283 return new DefaultRegisterBuilder()
284 .withIsProxyMapReply(proxyMapReplyFlag)
285 .withIsWantMapNotify(wantMapNotifyFlag)
Jian Li47671902016-08-11 01:18:18 +0900286 .withNonce(nonce)
287 .withKeyId(keyId)
288 .withAuthenticationData(authData)
289 .withMapRecords(mapRecords)
290 .build();
Jian Li26069e22016-08-10 22:00:52 +0900291 }
292 }
Jian Liedc5db12016-08-23 17:30:19 +0900293
294 /**
295 * LISP map register message writer class.
296 */
297 public static class RegisterWriter implements LispMessageWriter<LispMapRegister> {
298
Jian Liedc5db12016-08-23 17:30:19 +0900299 private static final int REGISTER_SHIFT_BIT = 4;
300
301 private static final int PROXY_MAP_REPLY_SHIFT_BIT = 3;
302
303 private static final int ENABLE_BIT = 1;
304 private static final int DISABLE_BIT = 0;
305
306 private static final int UNUSED_ZERO = 0;
307
308 @Override
309 public void writeTo(ByteBuf byteBuf, LispMapRegister message) throws LispWriterException {
310
311 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900312 byte msgType = (byte) (LispType.LISP_MAP_REGISTER.getTypeCode() << REGISTER_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900313
314 // proxy map reply flag
315 byte proxyMapReply = DISABLE_BIT;
316 if (message.isProxyMapReply()) {
317 proxyMapReply = (byte) (ENABLE_BIT << PROXY_MAP_REPLY_SHIFT_BIT);
318 }
319
320 byteBuf.writeByte(msgType + proxyMapReply);
321
322 // fill zero into reserved field
323 byteBuf.writeByte((short) UNUSED_ZERO);
324
325 // want map notify flag
326 byte wantMapNotify = DISABLE_BIT;
327 if (message.isWantMapNotify()) {
328 wantMapNotify = (byte) ENABLE_BIT;
329 }
330
331 byteBuf.writeByte(wantMapNotify);
332
333 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900334 byteBuf.writeByte(message.getMapRecords().size());
Jian Liedc5db12016-08-23 17:30:19 +0900335
336 // nonce
337 byteBuf.writeLong(message.getNonce());
338
339 // keyId
340 byteBuf.writeShort(message.getKeyId());
341
342 // authentication data length in octet
343 byteBuf.writeShort(message.getAuthDataLength());
344
345 // authentication data
346 byte[] data = message.getAuthenticationData();
347 byte[] clone;
348 if (data != null) {
349 clone = data.clone();
350 Arrays.fill(clone, (byte) UNUSED_ZERO);
351 }
352
353 byteBuf.writeBytes(data);
354
355 // TODO: need to implement MAC authentication mechanism
356
357 // serialize map records
Jian Lie4ba2a42016-08-29 20:24:15 +0900358 MapRecordWriter writer = new MapRecordWriter();
Jian Liedc5db12016-08-23 17:30:19 +0900359 List<LispMapRecord> records = message.getMapRecords();
360
361 for (int i = 0; i < records.size(); i++) {
362 writer.writeTo(byteBuf, records.get(i));
363 }
364 }
365 }
Jian Li451175e2016-07-19 23:22:20 +0900366}