blob: d82c4be93c49f2d8d2b3d506220effe861c87cb4 [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 Li5e505c62016-12-05 02:44:24 +090026import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordReader;
27import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordWriter;
Jian Lia7b394d2016-08-21 23:11:46 +090028
29import java.util.List;
Jian Li451175e2016-07-19 23:22:20 +090030
Jian Li20850d32016-08-04 02:15:57 +090031import static com.google.common.base.MoreObjects.toStringHelper;
32
Jian Li451175e2016-07-19 23:22:20 +090033/**
34 * Default LISP map reply message class.
35 */
Jian Liafe2d3f2016-11-01 02:49:07 +090036public final class DefaultLispMapReply extends AbstractLispMessage
37 implements LispMapReply {
Jian Lif59c0ad2016-08-02 18:11:30 +090038
39 private final long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090040 private final boolean probe;
41 private final boolean etr;
42 private final boolean security;
Jian Lia7b394d2016-08-21 23:11:46 +090043 private final List<LispMapRecord> mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090044
Yoonseon Hanca814bf2016-09-12 11:37:48 -070045 static final ReplyWriter WRITER;
46 static {
47 WRITER = new ReplyWriter();
48 }
49
Jian Lif59c0ad2016-08-02 18:11:30 +090050 /**
51 * A private constructor that protects object instantiation from external.
52 *
53 * @param nonce nonce
Jian Lif59c0ad2016-08-02 18:11:30 +090054 * @param probe probe flag
55 * @param etr etr flag
56 * @param security security flag
57 */
Jian Li42b3e432016-08-31 01:05:20 +090058 private DefaultLispMapReply(long nonce, boolean probe, boolean etr,
59 boolean security, List<LispMapRecord> mapRecords) {
Jian Lif59c0ad2016-08-02 18:11:30 +090060 this.nonce = nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090061 this.probe = probe;
62 this.etr = etr;
63 this.security = security;
Jian Lia7b394d2016-08-21 23:11:46 +090064 this.mapRecords = mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090065 }
66
Jian Li451175e2016-07-19 23:22:20 +090067 @Override
68 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090069 return LispType.LISP_MAP_REPLY;
Jian Li451175e2016-07-19 23:22:20 +090070 }
71
72 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070073 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
74 WRITER.writeTo(byteBuf, this);
Jian Li451175e2016-07-19 23:22:20 +090075 }
76
77 @Override
78 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090079 return new DefaultReplyBuilder();
Jian Li451175e2016-07-19 23:22:20 +090080 }
Jian Li719b3bf2016-07-22 00:38:29 +090081
82 @Override
83 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +090084 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +090085 }
86
87 @Override
88 public boolean isEtr() {
Jian Liedc5db12016-08-23 17:30:19 +090089 return etr;
Jian Li719b3bf2016-07-22 00:38:29 +090090 }
91
92 @Override
93 public boolean isSecurity() {
Jian Liedc5db12016-08-23 17:30:19 +090094 return security;
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 Liedc5db12016-08-23 17:30:19 +0900104 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900105 }
106
Jian Li20850d32016-08-04 02:15:57 +0900107 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900108 public List<LispMapRecord> getMapRecords() {
109 return ImmutableList.copyOf(mapRecords);
110 }
111
112 @Override
Jian Li20850d32016-08-04 02:15:57 +0900113 public String toString() {
114 return toStringHelper(this)
115 .add("type", getType())
116 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900117 .add("probe", probe)
118 .add("etr", etr)
Jian Lia7b394d2016-08-21 23:11:46 +0900119 .add("security", security)
120 .add("map records", mapRecords).toString();
Jian Li20850d32016-08-04 02:15:57 +0900121 }
122
123 @Override
124 public boolean equals(Object o) {
125 if (this == o) {
126 return true;
127 }
128 if (o == null || getClass() != o.getClass()) {
129 return false;
130 }
131 DefaultLispMapReply that = (DefaultLispMapReply) o;
132 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900133 Objects.equal(probe, that.probe) &&
134 Objects.equal(etr, that.etr) &&
Jian Lia7b394d2016-08-21 23:11:46 +0900135 Objects.equal(security, that.security) &&
136 Objects.equal(mapRecords, that.mapRecords);
Jian Li20850d32016-08-04 02:15:57 +0900137 }
138
139 @Override
140 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900141 return Objects.hashCode(nonce, probe, etr, security, mapRecords);
Jian Li20850d32016-08-04 02:15:57 +0900142 }
143
Jian Li719b3bf2016-07-22 00:38:29 +0900144 public static final class DefaultReplyBuilder implements ReplyBuilder {
145
Jian Lif59c0ad2016-08-02 18:11:30 +0900146 private long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +0900147 private boolean probe;
148 private boolean etr;
149 private boolean security;
Jian Lid4e63702016-08-30 18:29:20 +0900150 private List<LispMapRecord> mapRecords = Lists.newArrayList();
Jian Li719b3bf2016-07-22 00:38:29 +0900151
152 @Override
153 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900154 return LispType.LISP_MAP_REPLY;
Jian Li719b3bf2016-07-22 00:38:29 +0900155 }
156
157 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900158 public ReplyBuilder withIsProbe(boolean probe) {
159 this.probe = probe;
160 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900161 }
162
163 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900164 public ReplyBuilder withIsEtr(boolean etr) {
165 this.etr = etr;
166 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900167 }
168
169 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900170 public ReplyBuilder withIsSecurity(boolean security) {
171 this.security = security;
172 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900173 }
174
175 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900176 public ReplyBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900177 this.nonce = nonce;
178 return this;
179 }
180
181 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900182 public ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900183 if (this.mapRecords != null) {
184 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900185 }
Jian Lia7b394d2016-08-21 23:11:46 +0900186 return this;
187 }
188
189 @Override
Jian Li525fded2016-08-04 01:15:33 +0900190 public LispMapReply build() {
Jian Li42b3e432016-08-31 01:05:20 +0900191 return new DefaultLispMapReply(nonce, probe, etr, security, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900192 }
193 }
Jian Li26069e22016-08-10 22:00:52 +0900194
195 /**
Jian Liedc5db12016-08-23 17:30:19 +0900196 * A LISP message reader for MapReply message.
Jian Li26069e22016-08-10 22:00:52 +0900197 */
Jian Liedc5db12016-08-23 17:30:19 +0900198 public static final class ReplyReader implements LispMessageReader<LispMapReply> {
Jian Li26069e22016-08-10 22:00:52 +0900199
Jian Li47671902016-08-11 01:18:18 +0900200 private static final int PROBE_INDEX = 3;
201 private static final int ETR_INDEX = 2;
202 private static final int SECURITY_INDEX = 1;
203 private static final int RESERVED_SKIP_LENGTH = 2;
204
Jian Li26069e22016-08-10 22:00:52 +0900205 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900206 public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900207
208 if (byteBuf.readerIndex() != 0) {
209 return null;
210 }
211
212 byte typeWithFlags = byteBuf.readByte();
213
214 // probe -> 1 bit
215 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
216
217 // etr -> 1bit
218 boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);
219
220 // security -> 1 bit
221 boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);
222
223 // skip two bytes as they represent reserved fields
224 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
225
226 // record count -> 8 bits
227 byte recordCount = (byte) byteBuf.readUnsignedByte();
228
229 // nonce -> 64 bits
230 long nonce = byteBuf.readLong();
231
Jian Lia7b394d2016-08-21 23:11:46 +0900232 List<LispMapRecord> mapRecords = Lists.newArrayList();
233 for (int i = 0; i < recordCount; i++) {
Jian Li5e505c62016-12-05 02:44:24 +0900234 mapRecords.add(new MapRecordReader().readFrom(byteBuf));
Jian Lia7b394d2016-08-21 23:11:46 +0900235 }
Jian Li47671902016-08-11 01:18:18 +0900236
237 return new DefaultReplyBuilder()
238 .withIsProbe(probe)
239 .withIsEtr(etr)
240 .withIsSecurity(security)
Jian Li47671902016-08-11 01:18:18 +0900241 .withNonce(nonce)
Jian Lib26d3502016-08-31 01:43:24 +0900242 .withMapRecords(mapRecords)
Jian Li47671902016-08-11 01:18:18 +0900243 .build();
Jian Li26069e22016-08-10 22:00:52 +0900244 }
245 }
Jian Liedc5db12016-08-23 17:30:19 +0900246
247 /**
248 * A LISP message writer for MapReply message.
249 */
250 public static final class ReplyWriter implements LispMessageWriter<LispMapReply> {
251
Jian Liedc5db12016-08-23 17:30:19 +0900252 private static final int REPLY_SHIFT_BIT = 4;
253
254 private static final int PROBE_FLAG_SHIFT_BIT = 3;
255 private static final int ETR_FLAG_SHIFT_BIT = 2;
256 private static final int SECURITY_FLAG_SHIFT_BIT = 1;
257
258 private static final int ENABLE_BIT = 1;
259 private static final int DISABLE_BIT = 0;
260
261 private static final int UNUSED_ZERO = 0;
262
263 @Override
264 public void writeTo(ByteBuf byteBuf, LispMapReply message) throws LispWriterException {
265
266 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900267 byte msgType = (byte) (LispType.LISP_MAP_REPLY.getTypeCode() << REPLY_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900268
269 // probe flag
270 byte probe = DISABLE_BIT;
271 if (message.isProbe()) {
272 probe = (byte) (ENABLE_BIT << PROBE_FLAG_SHIFT_BIT);
273 }
274
275 // etr flag
276 byte etr = DISABLE_BIT;
277 if (message.isEtr()) {
278 etr = (byte) (ENABLE_BIT << ETR_FLAG_SHIFT_BIT);
279 }
280
281 // security flag
282 byte security = DISABLE_BIT;
283 if (message.isSecurity()) {
284 security = (byte) (ENABLE_BIT << SECURITY_FLAG_SHIFT_BIT);
285 }
286
287 byteBuf.writeByte((byte) (msgType + probe + etr + security));
288
289 // reserved field
290 byteBuf.writeShort((short) UNUSED_ZERO);
291
292 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900293 byteBuf.writeByte(message.getMapRecords().size());
Jian Liedc5db12016-08-23 17:30:19 +0900294
295 // nonce
296 byteBuf.writeLong(message.getNonce());
297
298 // serialize map records
299 MapRecordWriter writer = new MapRecordWriter();
300 List<LispMapRecord> records = message.getMapRecords();
301
302 for (int i = 0; i < records.size(); i++) {
303 writer.writeTo(byteBuf, records.get(i));
304 }
305 }
306 }
Jian Li451175e2016-07-19 23:22:20 +0900307}