blob: 74132452b82d0eeafcabeb9a96e98423964ebd38 [file] [log] [blame]
Jian Li27759352016-10-04 20:14:42 +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
18import io.netty.buffer.ByteBuf;
19import org.onlab.util.ByteOperator;
20import org.onlab.util.ImmutableByteSequence;
21import org.onosproject.lisp.msg.exceptions.LispParseError;
22import org.onosproject.lisp.msg.exceptions.LispReaderException;
23import org.onosproject.lisp.msg.exceptions.LispWriterException;
24import org.onosproject.lisp.msg.types.LispAfiAddress;
25import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
26
27import java.util.Arrays;
28
29/**
30 * A class that contains a set of helper methods for LISP info request and reply.
31 */
32public class DefaultLispInfo implements LispInfo {
33
34 protected final boolean infoReply;
35 protected final long nonce;
36 protected final short keyId;
37 protected final short authDataLength;
38 protected final byte[] authenticationData;
39 protected final int ttl;
40 protected final byte maskLength;
41 protected final LispAfiAddress eidPrefix;
42
43 private static final int INFO_REPLY_INDEX = 3;
44 private static final int RESERVED_SKIP_LENGTH_1 = 3;
45 private static final int RESERVED_SKIP_LENGTH_2 = 1;
46
47 private static final int INFO_REQUEST_SHIFT_BIT = 4;
48
49 private static final int ENABLE_BIT = 1;
50 private static final int DISABLE_BIT = 0;
51
52 private static final int UNUSED_ZERO = 0;
53
54 /**
55 * A private constructor that protects object instantiation from external.
56 *
57 * @param infoReply info reply flag
58 * @param nonce nonce
59 * @param keyId key identifier
60 * @param authDataLength authentication data length
61 * @param authenticationData authentication data
62 * @param ttl Time-To-Live value
63 * @param maskLength EID prefix mask length
64 * @param eidPrefix EID prefix
65 */
66 protected DefaultLispInfo(boolean infoReply, long nonce, short keyId, short authDataLength,
67 byte[] authenticationData, int ttl, byte maskLength,
68 LispAfiAddress eidPrefix) {
69 this.infoReply = infoReply;
70 this.nonce = nonce;
71 this.keyId = keyId;
72 this.authDataLength = authDataLength;
73 this.authenticationData = authenticationData;
74 this.ttl = ttl;
75 this.maskLength = maskLength;
76 this.eidPrefix = eidPrefix;
77 }
78
79 @Override
80 public LispType getType() {
81 return LispType.LISP_INFO;
82 }
83
84 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070085 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
86 serialize(byteBuf, this);
Jian Li27759352016-10-04 20:14:42 +090087 }
88
89 @Override
90 public Builder createBuilder() {
91 return new DefaultLispInfoRequest.DefaultInfoRequestBuilder();
92 }
93
94 @Override
95 public boolean hasInfoReply() {
96 return infoReply;
97 }
98
99 @Override
100 public long getNonce() {
101 return nonce;
102 }
103
104 @Override
105 public short getKeyId() {
106 return keyId;
107 }
108
109 @Override
110 public short getAuthDataLength() {
111 return authDataLength;
112 }
113
114 @Override
115 public byte[] getAuthenticationData() {
116 if (authenticationData != null && authenticationData.length != 0) {
117 return ImmutableByteSequence.copyFrom(authenticationData).asArray();
118 } else {
119 return new byte[0];
120 }
121 }
122
123 @Override
124 public int getTtl() {
125 return ttl;
126 }
127
128 @Override
129 public byte getMaskLength() {
130 return maskLength;
131 }
132
133 @Override
134 public LispAfiAddress getPrefix() {
135 return eidPrefix;
136 }
137
138 public static LispInfo deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException {
139
140 if (byteBuf.readerIndex() != 0) {
141 return null;
142 }
143
144 // infoReply -> 1 bit
145 boolean infoReplyFlag = ByteOperator.getBit(byteBuf.readByte(), INFO_REPLY_INDEX);
146
147 // let's skip the reserved field
148 byteBuf.skipBytes(RESERVED_SKIP_LENGTH_1);
149
150 // nonce -> 64 bits
151 long nonce = byteBuf.readLong();
152
153 // keyId -> 16 bits
154 short keyId = byteBuf.readShort();
155
156 // authenticationDataLength -> 16 bits
157 short authLength = byteBuf.readShort();
158
159 // authenticationData -> depends on the authenticationDataLength
160 byte[] authData = new byte[authLength];
161 byteBuf.readBytes(authData);
162
163 // ttl -> 32 bits
164 int ttl = byteBuf.readInt();
165
166 // let's skip the reserved field
167 byteBuf.skipBytes(RESERVED_SKIP_LENGTH_2);
168
169 // mask length -> 8 bits
170 short maskLength = byteBuf.readUnsignedByte();
171
172 LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
173
174 return new DefaultLispInfo(infoReplyFlag, nonce, keyId, authLength,
175 authData, ttl, (byte) maskLength, prefix);
176 }
177
178 public static void serialize(ByteBuf byteBuf, LispInfo message) throws LispWriterException {
179
180 // specify LISP message type
181 byte msgType = (byte) (LispType.LISP_INFO.getTypeCode() << INFO_REQUEST_SHIFT_BIT);
182
183 // info reply flag
184 byte infoReply = DISABLE_BIT;
185 if (message.hasInfoReply()) {
186 infoReply = (byte) (ENABLE_BIT << INFO_REPLY_INDEX);
187 }
188
189 byteBuf.writeByte(msgType + infoReply);
190
191 // fill zero into reserved filed
192 byteBuf.writeByte((short) UNUSED_ZERO);
193 byteBuf.writeByte((short) UNUSED_ZERO);
194 byteBuf.writeByte((short) UNUSED_ZERO);
195
196 // nonce
197 byteBuf.writeLong(message.getNonce());
198
199 // keyId
200 byteBuf.writeShort(message.getKeyId());
201
202 // authentication data length in octet
203 byteBuf.writeShort(message.getAuthDataLength());
204
205 // authentication data
206 byte[] data = message.getAuthenticationData();
207 byte[] clone;
208 if (data != null) {
209 clone = data.clone();
210 Arrays.fill(clone, (byte) UNUSED_ZERO);
211 }
212
213 byteBuf.writeBytes(data);
214
215 // TODO: need to implement MAC authentication mechanism
216
217 /// TTL
218 byteBuf.writeInt(message.getTtl());
219
220 // fill zero into reserved filed
221 byteBuf.writeByte((short) UNUSED_ZERO);
222
223 // mask length
224 byteBuf.writeByte(message.getMaskLength());
225
226 // EID prefix AFI with EID prefix
227 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
228 afiAddressWriter.writeTo(byteBuf, message.getPrefix());
229 }
230}