blob: 5d2257a0f7ad3fee63d4ef6da1d01f52808ccb34 [file] [log] [blame]
Jian Li10a09062016-07-26 23:58:50 +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 Li18f3bce2016-08-04 17:36:41 +090018import com.google.common.base.Objects;
Jian Li47671902016-08-11 01:18:18 +090019import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Lists;
Jian Li26069e22016-08-10 22:00:52 +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 Li672ebda2017-02-06 20:21:04 +090024import org.onosproject.lisp.msg.protocols.DefaultLispLocator.LocatorReader;
25import org.onosproject.lisp.msg.protocols.DefaultLispLocator.LocatorWriter;
Jian Li5e505c62016-12-05 02:44:24 +090026import org.onosproject.lisp.msg.types.LispAfiAddress;
Jian Lia7b394d2016-08-21 23:11:46 +090027import org.onosproject.lisp.msg.exceptions.LispReaderException;
Jian Liedc5db12016-08-23 17:30:19 +090028import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li5e505c62016-12-05 02:44:24 +090029import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
Jian Li10a09062016-07-26 23:58:50 +090030
Jian Li47671902016-08-11 01:18:18 +090031import java.util.List;
32
Jian Li18f3bce2016-08-04 17:36:41 +090033import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lid4e63702016-08-30 18:29:20 +090034import static com.google.common.base.Preconditions.checkNotNull;
Jian Li18f3bce2016-08-04 17:36:41 +090035
Jian Li10a09062016-07-26 23:58:50 +090036/**
37 * Default implementation of LispMapRecord.
38 */
Jian Li672ebda2017-02-06 20:21:04 +090039public final class DefaultLispMapRecord extends AbstractLispRecord
40 implements LispMapRecord {
Jian Li10a09062016-07-26 23:58:50 +090041
Jian Li672ebda2017-02-06 20:21:04 +090042 private final List<LispLocator> locators;
Jian Li10a09062016-07-26 23:58:50 +090043
Yoonseon Hanca814bf2016-09-12 11:37:48 -070044 static final MapRecordWriter WRITER;
45 static {
46 WRITER = new MapRecordWriter();
47 }
48
Jian Li631e62a2016-08-03 22:42:00 +090049 /**
50 * A private constructor that protects object instantiation from external.
51 *
52 * @param recordTtl record time-to-live value
Jian Li631e62a2016-08-03 22:42:00 +090053 * @param maskLength mask length
54 * @param action lisp map reply action
55 * @param authoritative authoritative flag
56 * @param mapVersionNumber map version number
57 * @param eidPrefixAfi EID prefix AFI address
Jian Li672ebda2017-02-06 20:21:04 +090058 * @param locators a collection of locators
Jian Li631e62a2016-08-03 22:42:00 +090059 */
Jian Li42b3e432016-08-31 01:05:20 +090060 private DefaultLispMapRecord(int recordTtl, byte maskLength,
Jian Li631e62a2016-08-03 22:42:00 +090061 LispMapReplyAction action, boolean authoritative,
Jian Li47671902016-08-11 01:18:18 +090062 short mapVersionNumber, LispAfiAddress eidPrefixAfi,
Jian Li672ebda2017-02-06 20:21:04 +090063 List<LispLocator> locators) {
64 super(recordTtl, maskLength, action, authoritative, mapVersionNumber, eidPrefixAfi);
65 this.locators = locators;
Jian Li10a09062016-07-26 23:58:50 +090066 }
67
Jian Li631e62a2016-08-03 22:42:00 +090068 @Override
Jian Li10a09062016-07-26 23:58:50 +090069 public int getLocatorCount() {
Jian Li672ebda2017-02-06 20:21:04 +090070 return locators.size();
Jian Li10a09062016-07-26 23:58:50 +090071 }
72
Jian Li631e62a2016-08-03 22:42:00 +090073 @Override
Jian Li672ebda2017-02-06 20:21:04 +090074 public List<LispLocator> getLocators() {
75 return ImmutableList.copyOf(locators);
Jian Li47671902016-08-11 01:18:18 +090076 }
77
78 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070079 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
80 WRITER.writeTo(byteBuf, this);
Jian Li47671902016-08-11 01:18:18 +090081 }
82
83 @Override
Jian Li18f3bce2016-08-04 17:36:41 +090084 public String toString() {
85 return toStringHelper(this)
86 .add("record TTL", recordTtl)
Jian Li18f3bce2016-08-04 17:36:41 +090087 .add("maskLength", maskLength)
88 .add("action", action)
89 .add("authoritative", authoritative)
90 .add("mapVersionNumber", mapVersionNumber)
Jian Li47671902016-08-11 01:18:18 +090091 .add("EID prefix AFI address", eidPrefixAfi)
Jian Li672ebda2017-02-06 20:21:04 +090092 .add("locators", locators)
93 .toString();
Jian Li18f3bce2016-08-04 17:36:41 +090094 }
95
96 @Override
97 public boolean equals(Object o) {
98 if (this == o) {
99 return true;
100 }
101 if (o == null || getClass() != o.getClass()) {
102 return false;
103 }
104 DefaultLispMapRecord that = (DefaultLispMapRecord) o;
105 return Objects.equal(recordTtl, that.recordTtl) &&
Jian Li18f3bce2016-08-04 17:36:41 +0900106 Objects.equal(maskLength, that.maskLength) &&
107 Objects.equal(action, that.action) &&
108 Objects.equal(authoritative, that.authoritative) &&
109 Objects.equal(mapVersionNumber, that.mapVersionNumber) &&
Jian Li47671902016-08-11 01:18:18 +0900110 Objects.equal(eidPrefixAfi, that.eidPrefixAfi) &&
Jian Li672ebda2017-02-06 20:21:04 +0900111 Objects.equal(locators, that.locators);
Jian Li18f3bce2016-08-04 17:36:41 +0900112 }
113
114 @Override
115 public int hashCode() {
Jian Li672ebda2017-02-06 20:21:04 +0900116 return Objects.hashCode(recordTtl, maskLength, action, authoritative,
117 mapVersionNumber, eidPrefixAfi, locators);
Jian Li18f3bce2016-08-04 17:36:41 +0900118 }
119
Jian Li672ebda2017-02-06 20:21:04 +0900120 public static final class DefaultMapRecordBuilder
121 extends AbstractRecordBuilder<MapRecordBuilder>
122 implements MapRecordBuilder {
Jian Li10a09062016-07-26 23:58:50 +0900123
Jian Li672ebda2017-02-06 20:21:04 +0900124 private List<LispLocator> locators = Lists.newArrayList();
Jian Li631e62a2016-08-03 22:42:00 +0900125
Jian Li10a09062016-07-26 23:58:50 +0900126 @Override
Jian Li672ebda2017-02-06 20:21:04 +0900127 public MapRecordBuilder withLocators(List<LispLocator> locators) {
128 if (locators != null) {
129 this.locators = ImmutableList.copyOf(locators);
Jian Lie4ba2a42016-08-29 20:24:15 +0900130 }
Jian Li47671902016-08-11 01:18:18 +0900131 return this;
132 }
133
134 @Override
Jian Li631e62a2016-08-03 22:42:00 +0900135 public LispMapRecord build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900136
Jian Lid4e63702016-08-30 18:29:20 +0900137 checkNotNull(eidPrefixAfi, "Must specify an EID prefix");
Jian Lie4ba2a42016-08-29 20:24:15 +0900138
Jian Li42b3e432016-08-31 01:05:20 +0900139 return new DefaultLispMapRecord(recordTtl, maskLength, action,
Jian Li672ebda2017-02-06 20:21:04 +0900140 authoritative, mapVersionNumber, eidPrefixAfi, locators);
Jian Li10a09062016-07-26 23:58:50 +0900141 }
142 }
Jian Li26069e22016-08-10 22:00:52 +0900143
144 /**
Jian Li47671902016-08-11 01:18:18 +0900145 * A LISP message reader for MapRecord portion.
Jian Li26069e22016-08-10 22:00:52 +0900146 */
Jian Li47671902016-08-11 01:18:18 +0900147 public static final class MapRecordReader implements LispMessageReader<LispMapRecord> {
148
149 private static final int AUTHORITATIVE_INDEX = 4;
150 private static final int RESERVED_SKIP_LENGTH = 1;
Jian Li26069e22016-08-10 22:00:52 +0900151
Jian Lie4ba2a42016-08-29 20:24:15 +0900152 private static final int REPLY_ACTION_SHIFT_BIT = 5;
153
Jian Li26069e22016-08-10 22:00:52 +0900154 @Override
Jian Li672ebda2017-02-06 20:21:04 +0900155 public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError,
156 LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900157
158 // Record TTL -> 32 bits
159 int recordTtl = byteBuf.readInt();
160
161 // Locator count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900162 int locatorCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900163
164 // EID mask length -> 8 bits
165 byte maskLength = (byte) byteBuf.readUnsignedByte();
166
Jian Lie4ba2a42016-08-29 20:24:15 +0900167 byte actionWithFlag = (byte) byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900168
Jian Lie4ba2a42016-08-29 20:24:15 +0900169 // action -> 3 bit
170 int actionByte = actionWithFlag >> REPLY_ACTION_SHIFT_BIT;
171 LispMapReplyAction action = LispMapReplyAction.valueOf(actionByte);
172 if (action == null) {
173 action = LispMapReplyAction.NoAction;
174 }
Jian Li47671902016-08-11 01:18:18 +0900175
176 // authoritative flag -> 1 bit
Jian Li672ebda2017-02-06 20:21:04 +0900177 boolean authoritative = ByteOperator.getBit((byte)
178 (actionWithFlag >> AUTHORITATIVE_INDEX), 0);
Jian Li47671902016-08-11 01:18:18 +0900179
180 // let's skip the reserved field
181 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
182
183 // Map version number -> 12 bits, we treat Rsvd field is all zero
184 short mapVersionNumber = (short) byteBuf.readUnsignedShort();
185
Jian Li672ebda2017-02-06 20:21:04 +0900186 LispAfiAddress eidPrefixAfi =
187 new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900188
Jian Li672ebda2017-02-06 20:21:04 +0900189 List<LispLocator> locators = Lists.newArrayList();
Jian Li47671902016-08-11 01:18:18 +0900190 for (int i = 0; i < locatorCount; i++) {
Jian Li672ebda2017-02-06 20:21:04 +0900191 locators.add(new LocatorReader().readFrom(byteBuf));
Jian Li47671902016-08-11 01:18:18 +0900192 }
193
194 return new DefaultMapRecordBuilder()
195 .withRecordTtl(recordTtl)
Jian Li47671902016-08-11 01:18:18 +0900196 .withMaskLength(maskLength)
Jian Lie4ba2a42016-08-29 20:24:15 +0900197 .withAction(action)
Jian Li672ebda2017-02-06 20:21:04 +0900198 .withIsAuthoritative(authoritative)
Jian Li47671902016-08-11 01:18:18 +0900199 .withMapVersionNumber(mapVersionNumber)
200 .withLocators(locators)
Jian Lia7b394d2016-08-21 23:11:46 +0900201 .withEidPrefixAfi(eidPrefixAfi)
Jian Li47671902016-08-11 01:18:18 +0900202 .build();
Jian Li26069e22016-08-10 22:00:52 +0900203 }
204 }
Jian Liedc5db12016-08-23 17:30:19 +0900205
206 /**
207 * A LISP message writer for MapRecord portion.
208 */
209 public static final class MapRecordWriter implements LispMessageWriter<LispMapRecord> {
210
211 private static final int REPLY_ACTION_SHIFT_BIT = 5;
212 private static final int AUTHORITATIVE_FLAG_SHIFT_BIT = 4;
213
214 private static final int ENABLE_BIT = 1;
215 private static final int DISABLE_BIT = 0;
216
217 @Override
218 public void writeTo(ByteBuf byteBuf, LispMapRecord message) throws LispWriterException {
219
220 // record TTL
221 byteBuf.writeInt(message.getRecordTtl());
222
223 // locator count
Jian Li42b3e432016-08-31 01:05:20 +0900224 byteBuf.writeByte((byte) message.getLocators().size());
Jian Liedc5db12016-08-23 17:30:19 +0900225
226 // EID mask length
227 byteBuf.writeByte(message.getMaskLength());
228
229 // reply action
230 byte action = (byte) (message.getAction().getAction() << REPLY_ACTION_SHIFT_BIT);
231
232 // authoritative bit
233 byte authoritative = DISABLE_BIT;
234 if (message.isAuthoritative()) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900235 authoritative = ENABLE_BIT << AUTHORITATIVE_FLAG_SHIFT_BIT;
Jian Liedc5db12016-08-23 17:30:19 +0900236 }
Jian Liedc5db12016-08-23 17:30:19 +0900237
238 byteBuf.writeByte((byte) (action + authoritative));
239
240 // fill zero into reserved field
241 byteBuf.writeByte((short) 0);
242
243 // map version number
244 byteBuf.writeShort(message.getMapVersionNumber());
245
246 // EID prefix AFI with EID prefix
247 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
248 afiAddressWriter.writeTo(byteBuf, message.getEidPrefixAfi());
249
250 // serialize locator
Jian Li672ebda2017-02-06 20:21:04 +0900251 LocatorWriter recordWriter = new LocatorWriter();
252 List<LispLocator> locators = message.getLocators();
Jian Liedc5db12016-08-23 17:30:19 +0900253 for (int i = 0; i < locators.size(); i++) {
254 recordWriter.writeTo(byteBuf, locators.get(i));
255 }
256 }
257 }
Jian Li10a09062016-07-26 23:58:50 +0900258}