blob: 75c1689638242a68da5f31b507c663240a221d2e [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 Lid4e63702016-08-30 18:29:20 +0900149 private List<LispMapRecord> mapRecords = Lists.newArrayList();
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) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900188 if (this.mapRecords != null) {
189 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900190 }
Jian Lia7b394d2016-08-21 23:11:46 +0900191 return this;
192 }
193
194 @Override
Jian Li525fded2016-08-04 01:15:33 +0900195 public LispMapReply build() {
Jian Lia7b394d2016-08-21 23:11:46 +0900196 return new DefaultLispMapReply(nonce, recordCount, probe, etr, security, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900197 }
198 }
Jian Li26069e22016-08-10 22:00:52 +0900199
200 /**
Jian Liedc5db12016-08-23 17:30:19 +0900201 * A LISP message reader for MapReply message.
Jian Li26069e22016-08-10 22:00:52 +0900202 */
Jian Liedc5db12016-08-23 17:30:19 +0900203 public static final class ReplyReader implements LispMessageReader<LispMapReply> {
Jian Li26069e22016-08-10 22:00:52 +0900204
Jian Li47671902016-08-11 01:18:18 +0900205 private static final int PROBE_INDEX = 3;
206 private static final int ETR_INDEX = 2;
207 private static final int SECURITY_INDEX = 1;
208 private static final int RESERVED_SKIP_LENGTH = 2;
209
Jian Li26069e22016-08-10 22:00:52 +0900210 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900211 public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900212
213 if (byteBuf.readerIndex() != 0) {
214 return null;
215 }
216
217 byte typeWithFlags = byteBuf.readByte();
218
219 // probe -> 1 bit
220 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
221
222 // etr -> 1bit
223 boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);
224
225 // security -> 1 bit
226 boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);
227
228 // skip two bytes as they represent reserved fields
229 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
230
231 // record count -> 8 bits
232 byte recordCount = (byte) byteBuf.readUnsignedByte();
233
234 // nonce -> 64 bits
235 long nonce = byteBuf.readLong();
236
Jian Lia7b394d2016-08-21 23:11:46 +0900237 List<LispMapRecord> mapRecords = Lists.newArrayList();
238 for (int i = 0; i < recordCount; i++) {
239 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
240 }
Jian Li47671902016-08-11 01:18:18 +0900241
242 return new DefaultReplyBuilder()
243 .withIsProbe(probe)
244 .withIsEtr(etr)
245 .withIsSecurity(security)
246 .withRecordCount(recordCount)
247 .withNonce(nonce)
248 .build();
Jian Li26069e22016-08-10 22:00:52 +0900249 }
250 }
Jian Liedc5db12016-08-23 17:30:19 +0900251
252 /**
253 * A LISP message writer for MapReply message.
254 */
255 public static final class ReplyWriter implements LispMessageWriter<LispMapReply> {
256
257 private static final int REPLY_MSG_TYPE = 2;
258 private static final int REPLY_SHIFT_BIT = 4;
259
260 private static final int PROBE_FLAG_SHIFT_BIT = 3;
261 private static final int ETR_FLAG_SHIFT_BIT = 2;
262 private static final int SECURITY_FLAG_SHIFT_BIT = 1;
263
264 private static final int ENABLE_BIT = 1;
265 private static final int DISABLE_BIT = 0;
266
267 private static final int UNUSED_ZERO = 0;
268
269 @Override
270 public void writeTo(ByteBuf byteBuf, LispMapReply message) throws LispWriterException {
271
272 // specify LISP message type
273 byte msgType = (byte) (REPLY_MSG_TYPE << REPLY_SHIFT_BIT);
274
275 // probe flag
276 byte probe = DISABLE_BIT;
277 if (message.isProbe()) {
278 probe = (byte) (ENABLE_BIT << PROBE_FLAG_SHIFT_BIT);
279 }
280
281 // etr flag
282 byte etr = DISABLE_BIT;
283 if (message.isEtr()) {
284 etr = (byte) (ENABLE_BIT << ETR_FLAG_SHIFT_BIT);
285 }
286
287 // security flag
288 byte security = DISABLE_BIT;
289 if (message.isSecurity()) {
290 security = (byte) (ENABLE_BIT << SECURITY_FLAG_SHIFT_BIT);
291 }
292
293 byteBuf.writeByte((byte) (msgType + probe + etr + security));
294
295 // reserved field
296 byteBuf.writeShort((short) UNUSED_ZERO);
297
298 // record count
299 byteBuf.writeByte(message.getRecordCount());
300
301 // nonce
302 byteBuf.writeLong(message.getNonce());
303
304 // serialize map records
305 MapRecordWriter writer = new MapRecordWriter();
306 List<LispMapRecord> records = message.getMapRecords();
307
308 for (int i = 0; i < records.size(); i++) {
309 writer.writeTo(byteBuf, records.get(i));
310 }
311 }
312 }
Jian Li451175e2016-07-19 23:22:20 +0900313}