blob: 5773be8b9e8c716f079a662e0764557e2cbc3b03 [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;
Jian Lif59c0ad2016-08-02 18:11:30 +090038 private final boolean probe;
39 private final boolean etr;
40 private final boolean security;
Jian Lia7b394d2016-08-21 23:11:46 +090041 private final List<LispMapRecord> mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090042
Yoonseon Hanca814bf2016-09-12 11:37:48 -070043 static final ReplyWriter WRITER;
44 static {
45 WRITER = new ReplyWriter();
46 }
47
Jian Lif59c0ad2016-08-02 18:11:30 +090048 /**
49 * A private constructor that protects object instantiation from external.
50 *
51 * @param nonce nonce
Jian Lif59c0ad2016-08-02 18:11:30 +090052 * @param probe probe flag
53 * @param etr etr flag
54 * @param security security flag
55 */
Jian Li42b3e432016-08-31 01:05:20 +090056 private DefaultLispMapReply(long nonce, boolean probe, boolean etr,
57 boolean security, List<LispMapRecord> mapRecords) {
Jian Lif59c0ad2016-08-02 18:11:30 +090058 this.nonce = nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090059 this.probe = probe;
60 this.etr = etr;
61 this.security = security;
Jian Lia7b394d2016-08-21 23:11:46 +090062 this.mapRecords = mapRecords;
Jian Lif59c0ad2016-08-02 18:11:30 +090063 }
64
Jian Li451175e2016-07-19 23:22:20 +090065 @Override
66 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090067 return LispType.LISP_MAP_REPLY;
Jian Li451175e2016-07-19 23:22:20 +090068 }
69
70 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070071 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
72 WRITER.writeTo(byteBuf, this);
Jian Li451175e2016-07-19 23:22:20 +090073 }
74
75 @Override
76 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090077 return new DefaultReplyBuilder();
Jian Li451175e2016-07-19 23:22:20 +090078 }
Jian Li719b3bf2016-07-22 00:38:29 +090079
80 @Override
81 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +090082 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +090083 }
84
85 @Override
86 public boolean isEtr() {
Jian Liedc5db12016-08-23 17:30:19 +090087 return etr;
Jian Li719b3bf2016-07-22 00:38:29 +090088 }
89
90 @Override
91 public boolean isSecurity() {
Jian Liedc5db12016-08-23 17:30:19 +090092 return security;
Jian Li719b3bf2016-07-22 00:38:29 +090093 }
94
95 @Override
Jian Li42b3e432016-08-31 01:05:20 +090096 public int getRecordCount() {
97 return mapRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +090098 }
99
100 @Override
101 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +0900102 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900103 }
104
Jian Li20850d32016-08-04 02:15:57 +0900105 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900106 public List<LispMapRecord> getMapRecords() {
107 return ImmutableList.copyOf(mapRecords);
108 }
109
110 @Override
Jian Li20850d32016-08-04 02:15:57 +0900111 public String toString() {
112 return toStringHelper(this)
113 .add("type", getType())
114 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900115 .add("probe", probe)
116 .add("etr", etr)
Jian Lia7b394d2016-08-21 23:11:46 +0900117 .add("security", security)
118 .add("map records", mapRecords).toString();
Jian Li20850d32016-08-04 02:15:57 +0900119 }
120
121 @Override
122 public boolean equals(Object o) {
123 if (this == o) {
124 return true;
125 }
126 if (o == null || getClass() != o.getClass()) {
127 return false;
128 }
129 DefaultLispMapReply that = (DefaultLispMapReply) o;
130 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900131 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 Li42b3e432016-08-31 01:05:20 +0900139 return Objects.hashCode(nonce, 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;
Jian Lif59c0ad2016-08-02 18:11:30 +0900145 private boolean probe;
146 private boolean etr;
147 private boolean security;
Jian Lid4e63702016-08-30 18:29:20 +0900148 private List<LispMapRecord> mapRecords = Lists.newArrayList();
Jian Li719b3bf2016-07-22 00:38:29 +0900149
150 @Override
151 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900152 return LispType.LISP_MAP_REPLY;
Jian Li719b3bf2016-07-22 00:38:29 +0900153 }
154
155 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900156 public ReplyBuilder withIsProbe(boolean probe) {
157 this.probe = probe;
158 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900159 }
160
161 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900162 public ReplyBuilder withIsEtr(boolean etr) {
163 this.etr = etr;
164 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900165 }
166
167 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900168 public ReplyBuilder withIsSecurity(boolean security) {
169 this.security = security;
170 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900171 }
172
173 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900174 public ReplyBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900175 this.nonce = nonce;
176 return this;
177 }
178
179 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900180 public ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900181 if (this.mapRecords != null) {
182 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900183 }
Jian Lia7b394d2016-08-21 23:11:46 +0900184 return this;
185 }
186
187 @Override
Jian Li525fded2016-08-04 01:15:33 +0900188 public LispMapReply build() {
Jian Li42b3e432016-08-31 01:05:20 +0900189 return new DefaultLispMapReply(nonce, probe, etr, security, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900190 }
191 }
Jian Li26069e22016-08-10 22:00:52 +0900192
193 /**
Jian Liedc5db12016-08-23 17:30:19 +0900194 * A LISP message reader for MapReply message.
Jian Li26069e22016-08-10 22:00:52 +0900195 */
Jian Liedc5db12016-08-23 17:30:19 +0900196 public static final class ReplyReader implements LispMessageReader<LispMapReply> {
Jian Li26069e22016-08-10 22:00:52 +0900197
Jian Li47671902016-08-11 01:18:18 +0900198 private static final int PROBE_INDEX = 3;
199 private static final int ETR_INDEX = 2;
200 private static final int SECURITY_INDEX = 1;
201 private static final int RESERVED_SKIP_LENGTH = 2;
202
Jian Li26069e22016-08-10 22:00:52 +0900203 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900204 public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900205
206 if (byteBuf.readerIndex() != 0) {
207 return null;
208 }
209
210 byte typeWithFlags = byteBuf.readByte();
211
212 // probe -> 1 bit
213 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
214
215 // etr -> 1bit
216 boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);
217
218 // security -> 1 bit
219 boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);
220
221 // skip two bytes as they represent reserved fields
222 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
223
224 // record count -> 8 bits
225 byte recordCount = (byte) byteBuf.readUnsignedByte();
226
227 // nonce -> 64 bits
228 long nonce = byteBuf.readLong();
229
Jian Lia7b394d2016-08-21 23:11:46 +0900230 List<LispMapRecord> mapRecords = Lists.newArrayList();
231 for (int i = 0; i < recordCount; i++) {
232 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
233 }
Jian Li47671902016-08-11 01:18:18 +0900234
235 return new DefaultReplyBuilder()
236 .withIsProbe(probe)
237 .withIsEtr(etr)
238 .withIsSecurity(security)
Jian Li47671902016-08-11 01:18:18 +0900239 .withNonce(nonce)
Jian Lib26d3502016-08-31 01:43:24 +0900240 .withMapRecords(mapRecords)
Jian Li47671902016-08-11 01:18:18 +0900241 .build();
Jian Li26069e22016-08-10 22:00:52 +0900242 }
243 }
Jian Liedc5db12016-08-23 17:30:19 +0900244
245 /**
246 * A LISP message writer for MapReply message.
247 */
248 public static final class ReplyWriter implements LispMessageWriter<LispMapReply> {
249
Jian Liedc5db12016-08-23 17:30:19 +0900250 private static final int REPLY_SHIFT_BIT = 4;
251
252 private static final int PROBE_FLAG_SHIFT_BIT = 3;
253 private static final int ETR_FLAG_SHIFT_BIT = 2;
254 private static final int SECURITY_FLAG_SHIFT_BIT = 1;
255
256 private static final int ENABLE_BIT = 1;
257 private static final int DISABLE_BIT = 0;
258
259 private static final int UNUSED_ZERO = 0;
260
261 @Override
262 public void writeTo(ByteBuf byteBuf, LispMapReply message) throws LispWriterException {
263
264 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900265 byte msgType = (byte) (LispType.LISP_MAP_REPLY.getTypeCode() << REPLY_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900266
267 // probe flag
268 byte probe = DISABLE_BIT;
269 if (message.isProbe()) {
270 probe = (byte) (ENABLE_BIT << PROBE_FLAG_SHIFT_BIT);
271 }
272
273 // etr flag
274 byte etr = DISABLE_BIT;
275 if (message.isEtr()) {
276 etr = (byte) (ENABLE_BIT << ETR_FLAG_SHIFT_BIT);
277 }
278
279 // security flag
280 byte security = DISABLE_BIT;
281 if (message.isSecurity()) {
282 security = (byte) (ENABLE_BIT << SECURITY_FLAG_SHIFT_BIT);
283 }
284
285 byteBuf.writeByte((byte) (msgType + probe + etr + security));
286
287 // reserved field
288 byteBuf.writeShort((short) UNUSED_ZERO);
289
290 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900291 byteBuf.writeByte(message.getMapRecords().size());
Jian Liedc5db12016-08-23 17:30:19 +0900292
293 // nonce
294 byteBuf.writeLong(message.getNonce());
295
296 // serialize map records
297 MapRecordWriter writer = new MapRecordWriter();
298 List<LispMapRecord> records = message.getMapRecords();
299
300 for (int i = 0; i < records.size(); i++) {
301 writer.writeTo(byteBuf, records.get(i));
302 }
303 }
304 }
Jian Li451175e2016-07-19 23:22:20 +0900305}