blob: 36782c2992a77a4662433b0410f317c5b1a47956 [file] [log] [blame]
Yoonseon Hanca814bf2016-09-12 11:37:48 -07001/*
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 */
16
17package org.onosproject.lisp.msg.protocols;
18
19import com.google.common.base.Objects;
20import io.netty.buffer.ByteBuf;
21import io.netty.buffer.Unpooled;
22import org.onlab.packet.Data;
23import org.onlab.packet.DeserializationException;
24import org.onlab.packet.IP;
25import org.onlab.packet.UDP;
26import org.onlab.util.ByteOperator;
27import org.onosproject.lisp.msg.exceptions.LispParseError;
28import org.onosproject.lisp.msg.exceptions.LispReaderException;
29import org.onosproject.lisp.msg.exceptions.LispWriterException;
30
31import static com.google.common.base.MoreObjects.toStringHelper;
32import static org.onosproject.lisp.msg.protocols.LispType.LISP_ENCAPSULATED_CONTROL;
33
34/**
35 * Default LISP Encapsulated Control message class.
36 */
37public final class DefaultLispEncapsulatedControl
38 implements LispEncapsulatedControl {
39
40 private final boolean isSecurity;
41 private final IP innerIpHeader;
42 private final UDP innerUdp;
43 private final LispMessage innerMessage;
44
45 static final EcmWriter WRITER;
46 static {
47 WRITER = new EcmWriter();
48 }
49
50 /**
51 * A private constructor that protects object instantiation from external.
52 *
53 * @param isSecurity a security flag
54 * @param innerIpHeader a inner IP Header
55 * @param innerUdp a inner UDP Header
56 * @param innerMessage a inner LISP control message
57 */
58 private DefaultLispEncapsulatedControl(boolean isSecurity, IP innerIpHeader,
59 UDP innerUdp, LispMessage innerMessage) {
60 this.isSecurity = isSecurity;
61 this.innerIpHeader = innerIpHeader;
62 this.innerUdp = innerUdp;
63 this.innerMessage = innerMessage;
64 }
65
66 @Override
67 public LispType getType() {
68 return LISP_ENCAPSULATED_CONTROL;
69 }
70
71 @Override
72 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
73 WRITER.writeTo(byteBuf, this);
74 }
75
76 @Override
77 public Builder createBuilder() {
78 return new DefaultEcmBuilder();
79 }
80
81 @Override
82 public boolean isSecurity() {
83 return isSecurity;
84 }
85
86 @Override
87 public IP innerIpHeader() {
88 return innerIpHeader;
89 }
90
91 public UDP innerUdp() {
92 return innerUdp;
93 }
94
95 @Override
96 public LispMessage getControlMessage() {
97 return innerMessage;
98 }
99
100 @Override
101 public String toString() {
102 return toStringHelper(this)
103 .add("type", getType())
104 .add("isSecurity", isSecurity)
105 .add("inner IP header", innerIpHeader)
106 .add("inner UDP header", innerUdp)
107 .add("inner lisp Message", innerMessage)
108 .toString();
109 }
110
111 @Override
112 public boolean equals(Object o) {
113 if (this == o) {
114 return true;
115 }
116 if (o == null || getClass() != o.getClass()) {
117 return false;
118 }
119
120 DefaultLispEncapsulatedControl that = (DefaultLispEncapsulatedControl) o;
121 return Objects.equal(isSecurity, that.isSecurity) &&
122 Objects.equal(innerIpHeader, that.innerIpHeader) &&
123 Objects.equal(innerUdp, that.innerUdp) &&
124 Objects.equal(innerMessage, that.innerMessage);
125 }
126
127 @Override
128 public int hashCode() {
129 return Objects.hashCode(isSecurity, innerIpHeader, innerUdp, innerMessage);
130 }
131
132 /**
133 * LISP ECM Builder implementation.
134 */
135 public static final class DefaultEcmBuilder implements EcmBuilder {
136
137 private boolean isSecurity;
138 private IP innerIpHeader;
139 private UDP innerUdpHeader;
140 private LispMessage innerMessage;
141
142 @Override
143 public LispType getType() {
144 return LispType.LISP_ENCAPSULATED_CONTROL;
145 }
146
147 @Override
148 public EcmBuilder isSecurity(boolean security) {
149 this.isSecurity = security;
150 return this;
151 }
152
153 @Override
154 public EcmBuilder innerIpHeader(IP innerIpHeader) {
155 this.innerIpHeader = innerIpHeader;
156 return this;
157 }
158
159 @Override
160 public EcmBuilder innerUdpHeader(UDP innerUdpHeader) {
161 this.innerUdpHeader = innerUdpHeader;
162 return this;
163 }
164
165 @Override
166 public EcmBuilder innerLispMessage(LispMessage msg) {
167 this.innerMessage = msg;
168 return this;
169 }
170
171 @Override
172 public LispEncapsulatedControl build() {
173 return new DefaultLispEncapsulatedControl(isSecurity, innerIpHeader,
174 innerUdpHeader, innerMessage);
175 }
176 }
177
178 /**
179 * A LISP message reader for ECM.
180 */
181 public static final class EcmReader
182 implements LispMessageReader<LispEncapsulatedControl> {
183
184 private static final int SECURITY_INDEX = 3;
185 private static final int RESERVED_SKIP_LENGTH = 3;
186 private static final int UDP_HEADER_LENGTH = 8;
187 private static final short HEADER_LENGTH_MASK = 0xf;
188
189 @Override
190 public LispEncapsulatedControl readFrom(ByteBuf byteBuf) throws
191 LispParseError, LispReaderException, DeserializationException {
192
193 if (byteBuf.readerIndex() != 0) {
194 return null;
195 }
196
197 boolean securityFlag = ByteOperator.getBit(byteBuf.readByte(),
198 SECURITY_INDEX);
199 // let's skip the reserved field
200 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
201
202 short totalLength = byteBuf.getShort(byteBuf.readerIndex() + 2);
203
204 byte[] ipHeaderByte = new byte[totalLength];
205 byteBuf.getBytes(byteBuf.readerIndex(), ipHeaderByte, 0, totalLength);
206
207 IP innerIpHeader = IP.deserializer().deserialize(ipHeaderByte, 0,
208 totalLength);
209
210 UDP innerUdp = (UDP) innerIpHeader.getPayload();
211 Data data = (Data) innerUdp.getPayload();
212 ByteBuf msgBuffer = Unpooled.buffer();
213 msgBuffer.writeBytes(data.getData());
214
215 LispMessageReader reader = LispMessageReaderFactory.getReader(msgBuffer);
216 LispMessage innerMessage = (LispMessage) reader.readFrom(msgBuffer);
217
218 return new DefaultLispEncapsulatedControl(securityFlag, innerIpHeader,
219 innerUdp, innerMessage);
220 }
221 }
222
223 /**
224 * LISP ECM writer class.
225 */
226 public static class EcmWriter
227 implements LispMessageWriter<LispEncapsulatedControl> {
228
229 private static final short ECM_MSG_CODE =
230 LispType.LISP_ENCAPSULATED_CONTROL.getTypeCode();
231 private static final int TYPE_SHIFT_BIT = 4;
232
233 private static final int SECURITY_SHIFT_BIT = 3;
234
235 private static final int ENABLE_BIT = 1;
236 private static final int DISABLE_BIT = 0;
237
238 private static final int UNUSED_ZERO = 0;
239
240 @Override
241 public void writeTo(ByteBuf byteBuf, LispEncapsulatedControl message)
242 throws LispWriterException {
243
244 // specify LISP message type
245 byte msgType = (byte) (ECM_MSG_CODE << TYPE_SHIFT_BIT);
246
247 byte security = DISABLE_BIT;
248 if (message.isSecurity()) {
249 security = (byte) (ENABLE_BIT << SECURITY_SHIFT_BIT);
250 }
251
252 byteBuf.writeByte(msgType + security);
253
254 // fill zero into reserved field
255 byteBuf.writeByte((byte) UNUSED_ZERO);
256 byteBuf.writeByte((byte) UNUSED_ZERO);
257 byteBuf.writeByte((byte) UNUSED_ZERO);
258
259 ByteBuf buffer = Unpooled.buffer();
260 message.getControlMessage().writeTo(buffer);
261 byte[] dataBytes = new byte[buffer.writerIndex()];
262 buffer.getBytes(0, dataBytes, 0, buffer.writerIndex());
263
264 message.innerUdp().setPayload(new Data(dataBytes));
265 message.innerIpHeader().setPayload(message.innerUdp());
266
267 byteBuf.writeBytes(message.innerIpHeader().serialize());
268 }
269 }
270
271}