blob: 220bf7eec7b062697d8443005d8375cc40b87d7f [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 Lia7b394d2016-08-21 23:11:46 +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 Lia7b394d2016-08-21 23:11:46 +090026
27import java.util.List;
Jian Li451175e2016-07-19 23:22:20 +090028
Jian Li20850d32016-08-04 02:15:57 +090029import static com.google.common.base.MoreObjects.toStringHelper;
Jian Liedc5db12016-08-23 17:30:19 +090030import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordWriter;
Jian Li20850d32016-08-04 02:15:57 +090031
Jian Li451175e2016-07-19 23:22:20 +090032/**
33 * Default LISP map reply message class.
34 */
Jian Lif59c0ad2016-08-02 18:11:30 +090035public final class DefaultLispMapReply implements LispMapReply {
36
37 private final long nonce;
38 private final byte recordCount;
39 private final boolean probe;
40 private final boolean etr;
41 private final boolean security;
Jian Lia7b394d2016-08-21 23:11:46 +090042 private final List<LispMapRecord> mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090043
44 /**
45 * A private constructor that protects object instantiation from external.
46 *
47 * @param nonce nonce
48 * @param recordCount record count number
49 * @param probe probe flag
50 * @param etr etr flag
51 * @param security security flag
52 */
53 private DefaultLispMapReply(long nonce, byte recordCount, boolean probe,
Jian Lia7b394d2016-08-21 23:11:46 +090054 boolean etr, boolean security, List<LispMapRecord> mapRecords) {
Jian Lif59c0ad2016-08-02 18:11:30 +090055 this.nonce = nonce;
56 this.recordCount = recordCount;
57 this.probe = probe;
58 this.etr = etr;
59 this.security = security;
Jian Lia7b394d2016-08-21 23:11:46 +090060 this.mapRecords = mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090061 }
62
Jian Li451175e2016-07-19 23:22:20 +090063 @Override
64 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090065 return LispType.LISP_MAP_REPLY;
Jian Li451175e2016-07-19 23:22:20 +090066 }
67
68 @Override
69 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090070 // TODO: serialize LispMapReply message
Jian Li451175e2016-07-19 23:22:20 +090071 }
72
73 @Override
74 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090075 return new DefaultReplyBuilder();
Jian Li451175e2016-07-19 23:22:20 +090076 }
Jian Li719b3bf2016-07-22 00:38:29 +090077
78 @Override
79 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +090080 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +090081 }
82
83 @Override
84 public boolean isEtr() {
Jian Liedc5db12016-08-23 17:30:19 +090085 return etr;
Jian Li719b3bf2016-07-22 00:38:29 +090086 }
87
88 @Override
89 public boolean isSecurity() {
Jian Liedc5db12016-08-23 17:30:19 +090090 return security;
Jian Li719b3bf2016-07-22 00:38:29 +090091 }
92
93 @Override
94 public byte getRecordCount() {
Jian Liedc5db12016-08-23 17:30:19 +090095 return recordCount;
Jian Li719b3bf2016-07-22 00:38:29 +090096 }
97
98 @Override
99 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +0900100 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900101 }
102
Jian Li20850d32016-08-04 02:15:57 +0900103 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900104 public List<LispMapRecord> getMapRecords() {
105 return ImmutableList.copyOf(mapRecords);
106 }
107
108 @Override
Jian Li20850d32016-08-04 02:15:57 +0900109 public String toString() {
110 return toStringHelper(this)
111 .add("type", getType())
112 .add("nonce", nonce)
113 .add("recordCount", recordCount)
114 .add("probe", probe)
115 .add("etr", etr)
Jian Lia7b394d2016-08-21 23:11:46 +0900116 .add("security", security)
117 .add("map records", mapRecords).toString();
Jian Li20850d32016-08-04 02:15:57 +0900118 }
119
120 @Override
121 public boolean equals(Object o) {
122 if (this == o) {
123 return true;
124 }
125 if (o == null || getClass() != o.getClass()) {
126 return false;
127 }
128 DefaultLispMapReply that = (DefaultLispMapReply) o;
129 return Objects.equal(nonce, that.nonce) &&
130 Objects.equal(recordCount, that.recordCount) &&
131 Objects.equal(probe, that.probe) &&
132 Objects.equal(etr, that.etr) &&
Jian Lia7b394d2016-08-21 23:11:46 +0900133 Objects.equal(security, that.security) &&
134 Objects.equal(mapRecords, that.mapRecords);
Jian Li20850d32016-08-04 02:15:57 +0900135 }
136
137 @Override
138 public int hashCode() {
Jian Lia7b394d2016-08-21 23:11:46 +0900139 return Objects.hashCode(nonce, recordCount, probe, etr, security, mapRecords);
Jian Li20850d32016-08-04 02:15:57 +0900140 }
141
Jian Li719b3bf2016-07-22 00:38:29 +0900142 public static final class DefaultReplyBuilder implements ReplyBuilder {
143
Jian Lif59c0ad2016-08-02 18:11:30 +0900144 private long nonce;
145 private byte recordCount;
146 private boolean probe;
147 private boolean etr;
148 private boolean security;
Jian Lia7b394d2016-08-21 23:11:46 +0900149 private List<LispMapRecord> mapRecords;
Jian Li719b3bf2016-07-22 00:38:29 +0900150
151 @Override
152 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900153 return LispType.LISP_MAP_REPLY;
Jian Li719b3bf2016-07-22 00:38:29 +0900154 }
155
156 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900157 public ReplyBuilder withIsProbe(boolean probe) {
158 this.probe = probe;
159 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900160 }
161
162 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900163 public ReplyBuilder withIsEtr(boolean etr) {
164 this.etr = etr;
165 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900166 }
167
168 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900169 public ReplyBuilder withIsSecurity(boolean security) {
170 this.security = security;
171 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900172 }
173
174 @Override
175 public ReplyBuilder withRecordCount(byte recordCount) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900176 this.recordCount = recordCount;
177 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900178 }
179
180 @Override
181 public ReplyBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900182 this.nonce = nonce;
183 return this;
184 }
185
186 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900187 public ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
188 this.mapRecords = ImmutableList.copyOf(mapRecords);
189 return this;
190 }
191
192 @Override
Jian Li525fded2016-08-04 01:15:33 +0900193 public LispMapReply build() {
Jian Lia7b394d2016-08-21 23:11:46 +0900194 return new DefaultLispMapReply(nonce, recordCount, probe, etr, security, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900195 }
196 }
Jian Li26069e22016-08-10 22:00:52 +0900197
198 /**
Jian Liedc5db12016-08-23 17:30:19 +0900199 * A LISP message reader for MapReply message.
Jian Li26069e22016-08-10 22:00:52 +0900200 */
Jian Liedc5db12016-08-23 17:30:19 +0900201 public static final class ReplyReader implements LispMessageReader<LispMapReply> {
Jian Li26069e22016-08-10 22:00:52 +0900202
Jian Li47671902016-08-11 01:18:18 +0900203 private static final int PROBE_INDEX = 3;
204 private static final int ETR_INDEX = 2;
205 private static final int SECURITY_INDEX = 1;
206 private static final int RESERVED_SKIP_LENGTH = 2;
207
Jian Li26069e22016-08-10 22:00:52 +0900208 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900209 public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900210
211 if (byteBuf.readerIndex() != 0) {
212 return null;
213 }
214
215 byte typeWithFlags = byteBuf.readByte();
216
217 // probe -> 1 bit
218 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
219
220 // etr -> 1bit
221 boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);
222
223 // security -> 1 bit
224 boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);
225
226 // skip two bytes as they represent reserved fields
227 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
228
229 // record count -> 8 bits
230 byte recordCount = (byte) byteBuf.readUnsignedByte();
231
232 // nonce -> 64 bits
233 long nonce = byteBuf.readLong();
234
Jian Lia7b394d2016-08-21 23:11:46 +0900235 List<LispMapRecord> mapRecords = Lists.newArrayList();
236 for (int i = 0; i < recordCount; i++) {
237 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
238 }
Jian Li47671902016-08-11 01:18:18 +0900239
240 return new DefaultReplyBuilder()
241 .withIsProbe(probe)
242 .withIsEtr(etr)
243 .withIsSecurity(security)
244 .withRecordCount(recordCount)
245 .withNonce(nonce)
246 .build();
Jian Li26069e22016-08-10 22:00:52 +0900247 }
248 }
Jian Liedc5db12016-08-23 17:30:19 +0900249
250 /**
251 * A LISP message writer for MapReply message.
252 */
253 public static final class ReplyWriter implements LispMessageWriter<LispMapReply> {
254
255 private static final int REPLY_MSG_TYPE = 2;
256 private static final int REPLY_SHIFT_BIT = 4;
257
258 private static final int PROBE_FLAG_SHIFT_BIT = 3;
259 private static final int ETR_FLAG_SHIFT_BIT = 2;
260 private static final int SECURITY_FLAG_SHIFT_BIT = 1;
261
262 private static final int ENABLE_BIT = 1;
263 private static final int DISABLE_BIT = 0;
264
265 private static final int UNUSED_ZERO = 0;
266
267 @Override
268 public void writeTo(ByteBuf byteBuf, LispMapReply message) throws LispWriterException {
269
270 // specify LISP message type
271 byte msgType = (byte) (REPLY_MSG_TYPE << REPLY_SHIFT_BIT);
272
273 // probe flag
274 byte probe = DISABLE_BIT;
275 if (message.isProbe()) {
276 probe = (byte) (ENABLE_BIT << PROBE_FLAG_SHIFT_BIT);
277 }
278
279 // etr flag
280 byte etr = DISABLE_BIT;
281 if (message.isEtr()) {
282 etr = (byte) (ENABLE_BIT << ETR_FLAG_SHIFT_BIT);
283 }
284
285 // security flag
286 byte security = DISABLE_BIT;
287 if (message.isSecurity()) {
288 security = (byte) (ENABLE_BIT << SECURITY_FLAG_SHIFT_BIT);
289 }
290
291 byteBuf.writeByte((byte) (msgType + probe + etr + security));
292
293 // reserved field
294 byteBuf.writeShort((short) UNUSED_ZERO);
295
296 // record count
297 byteBuf.writeByte(message.getRecordCount());
298
299 // nonce
300 byteBuf.writeLong(message.getNonce());
301
302 // serialize map records
303 MapRecordWriter writer = new MapRecordWriter();
304 List<LispMapRecord> records = message.getMapRecords();
305
306 for (int i = 0; i < records.size(); i++) {
307 writer.writeTo(byteBuf, records.get(i));
308 }
309 }
310 }
Jian Li451175e2016-07-19 23:22:20 +0900311}