blob: fea7f5224c64fdc42f1ba23a8a152b191fcbd70d [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 Liafe2d3f2016-11-01 02:49:07 +090035public final class DefaultLispMapReply extends AbstractLispMessage
36 implements LispMapReply {
Jian Lif59c0ad2016-08-02 18:11:30 +090037
38 private final long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090039 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
Yoonseon Hanca814bf2016-09-12 11:37:48 -070044 static final ReplyWriter WRITER;
45 static {
46 WRITER = new ReplyWriter();
47 }
48
Jian Lif59c0ad2016-08-02 18:11:30 +090049 /**
50 * A private constructor that protects object instantiation from external.
51 *
52 * @param nonce nonce
Jian Lif59c0ad2016-08-02 18:11:30 +090053 * @param probe probe flag
54 * @param etr etr flag
55 * @param security security flag
56 */
Jian Li42b3e432016-08-31 01:05:20 +090057 private DefaultLispMapReply(long nonce, boolean probe, boolean etr,
58 boolean security, List<LispMapRecord> mapRecords) {
Jian Lif59c0ad2016-08-02 18:11:30 +090059 this.nonce = nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090060 this.probe = probe;
61 this.etr = etr;
62 this.security = security;
Jian Lia7b394d2016-08-21 23:11:46 +090063 this.mapRecords = mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090064 }
65
Jian Li451175e2016-07-19 23:22:20 +090066 @Override
67 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090068 return LispType.LISP_MAP_REPLY;
Jian Li451175e2016-07-19 23:22:20 +090069 }
70
71 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070072 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
73 WRITER.writeTo(byteBuf, this);
Jian Li451175e2016-07-19 23:22:20 +090074 }
75
76 @Override
77 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090078 return new DefaultReplyBuilder();
Jian Li451175e2016-07-19 23:22:20 +090079 }
Jian Li719b3bf2016-07-22 00:38:29 +090080
81 @Override
82 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +090083 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +090084 }
85
86 @Override
87 public boolean isEtr() {
Jian Liedc5db12016-08-23 17:30:19 +090088 return etr;
Jian Li719b3bf2016-07-22 00:38:29 +090089 }
90
91 @Override
92 public boolean isSecurity() {
Jian Liedc5db12016-08-23 17:30:19 +090093 return security;
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 Liedc5db12016-08-23 17:30:19 +0900103 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900104 }
105
Jian Li20850d32016-08-04 02:15:57 +0900106 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900107 public List<LispMapRecord> getMapRecords() {
108 return ImmutableList.copyOf(mapRecords);
109 }
110
111 @Override
Jian Li20850d32016-08-04 02:15:57 +0900112 public String toString() {
113 return toStringHelper(this)
114 .add("type", getType())
115 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900116 .add("probe", probe)
117 .add("etr", etr)
Jian Lia7b394d2016-08-21 23:11:46 +0900118 .add("security", security)
119 .add("map records", mapRecords).toString();
Jian Li20850d32016-08-04 02:15:57 +0900120 }
121
122 @Override
123 public boolean equals(Object o) {
124 if (this == o) {
125 return true;
126 }
127 if (o == null || getClass() != o.getClass()) {
128 return false;
129 }
130 DefaultLispMapReply that = (DefaultLispMapReply) o;
131 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900132 Objects.equal(probe, that.probe) &&
133 Objects.equal(etr, that.etr) &&
Jian Lia7b394d2016-08-21 23:11:46 +0900134 Objects.equal(security, that.security) &&
135 Objects.equal(mapRecords, that.mapRecords);
Jian Li20850d32016-08-04 02:15:57 +0900136 }
137
138 @Override
139 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900140 return Objects.hashCode(nonce, probe, etr, security, mapRecords);
Jian Li20850d32016-08-04 02:15:57 +0900141 }
142
Jian Li719b3bf2016-07-22 00:38:29 +0900143 public static final class DefaultReplyBuilder implements ReplyBuilder {
144
Jian Lif59c0ad2016-08-02 18:11:30 +0900145 private long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +0900146 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
Jian Li719b3bf2016-07-22 00:38:29 +0900175 public ReplyBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900176 this.nonce = nonce;
177 return this;
178 }
179
180 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900181 public ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900182 if (this.mapRecords != null) {
183 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900184 }
Jian Lia7b394d2016-08-21 23:11:46 +0900185 return this;
186 }
187
188 @Override
Jian Li525fded2016-08-04 01:15:33 +0900189 public LispMapReply build() {
Jian Li42b3e432016-08-31 01:05:20 +0900190 return new DefaultLispMapReply(nonce, probe, etr, security, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900191 }
192 }
Jian Li26069e22016-08-10 22:00:52 +0900193
194 /**
Jian Liedc5db12016-08-23 17:30:19 +0900195 * A LISP message reader for MapReply message.
Jian Li26069e22016-08-10 22:00:52 +0900196 */
Jian Liedc5db12016-08-23 17:30:19 +0900197 public static final class ReplyReader implements LispMessageReader<LispMapReply> {
Jian Li26069e22016-08-10 22:00:52 +0900198
Jian Li47671902016-08-11 01:18:18 +0900199 private static final int PROBE_INDEX = 3;
200 private static final int ETR_INDEX = 2;
201 private static final int SECURITY_INDEX = 1;
202 private static final int RESERVED_SKIP_LENGTH = 2;
203
Jian Li26069e22016-08-10 22:00:52 +0900204 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900205 public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900206
207 if (byteBuf.readerIndex() != 0) {
208 return null;
209 }
210
211 byte typeWithFlags = byteBuf.readByte();
212
213 // probe -> 1 bit
214 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
215
216 // etr -> 1bit
217 boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);
218
219 // security -> 1 bit
220 boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);
221
222 // skip two bytes as they represent reserved fields
223 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
224
225 // record count -> 8 bits
226 byte recordCount = (byte) byteBuf.readUnsignedByte();
227
228 // nonce -> 64 bits
229 long nonce = byteBuf.readLong();
230
Jian Lia7b394d2016-08-21 23:11:46 +0900231 List<LispMapRecord> mapRecords = Lists.newArrayList();
232 for (int i = 0; i < recordCount; i++) {
233 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
234 }
Jian Li47671902016-08-11 01:18:18 +0900235
236 return new DefaultReplyBuilder()
237 .withIsProbe(probe)
238 .withIsEtr(etr)
239 .withIsSecurity(security)
Jian Li47671902016-08-11 01:18:18 +0900240 .withNonce(nonce)
Jian Lib26d3502016-08-31 01:43:24 +0900241 .withMapRecords(mapRecords)
Jian Li47671902016-08-11 01:18:18 +0900242 .build();
Jian Li26069e22016-08-10 22:00:52 +0900243 }
244 }
Jian Liedc5db12016-08-23 17:30:19 +0900245
246 /**
247 * A LISP message writer for MapReply message.
248 */
249 public static final class ReplyWriter implements LispMessageWriter<LispMapReply> {
250
Jian Liedc5db12016-08-23 17:30:19 +0900251 private static final int REPLY_SHIFT_BIT = 4;
252
253 private static final int PROBE_FLAG_SHIFT_BIT = 3;
254 private static final int ETR_FLAG_SHIFT_BIT = 2;
255 private static final int SECURITY_FLAG_SHIFT_BIT = 1;
256
257 private static final int ENABLE_BIT = 1;
258 private static final int DISABLE_BIT = 0;
259
260 private static final int UNUSED_ZERO = 0;
261
262 @Override
263 public void writeTo(ByteBuf byteBuf, LispMapReply message) throws LispWriterException {
264
265 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900266 byte msgType = (byte) (LispType.LISP_MAP_REPLY.getTypeCode() << REPLY_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900267
268 // probe flag
269 byte probe = DISABLE_BIT;
270 if (message.isProbe()) {
271 probe = (byte) (ENABLE_BIT << PROBE_FLAG_SHIFT_BIT);
272 }
273
274 // etr flag
275 byte etr = DISABLE_BIT;
276 if (message.isEtr()) {
277 etr = (byte) (ENABLE_BIT << ETR_FLAG_SHIFT_BIT);
278 }
279
280 // security flag
281 byte security = DISABLE_BIT;
282 if (message.isSecurity()) {
283 security = (byte) (ENABLE_BIT << SECURITY_FLAG_SHIFT_BIT);
284 }
285
286 byteBuf.writeByte((byte) (msgType + probe + etr + security));
287
288 // reserved field
289 byteBuf.writeShort((short) UNUSED_ZERO);
290
291 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900292 byteBuf.writeByte(message.getMapRecords().size());
Jian Liedc5db12016-08-23 17:30:19 +0900293
294 // nonce
295 byteBuf.writeLong(message.getNonce());
296
297 // serialize map records
298 MapRecordWriter writer = new MapRecordWriter();
299 List<LispMapRecord> records = message.getMapRecords();
300
301 for (int i = 0; i < records.size(); i++) {
302 writer.writeTo(byteBuf, records.get(i));
303 }
304 }
305 }
Jian Li451175e2016-07-19 23:22:20 +0900306}