[ONOS-5427] Add LISP Info-Request and Info-Reply message type
Change-Id: Ia54919945609a57e45b34af3bbe7b04e4a7efbec
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfo.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfo.java
new file mode 100644
index 0000000..14cd884
--- /dev/null
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispInfo.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.msg.protocols;
+
+import io.netty.buffer.ByteBuf;
+import org.onlab.util.ByteOperator;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
+import org.onosproject.lisp.msg.exceptions.LispWriterException;
+import org.onosproject.lisp.msg.types.LispAfiAddress;
+import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
+
+import java.util.Arrays;
+
+/**
+ * A class that contains a set of helper methods for LISP info request and reply.
+ */
+public class DefaultLispInfo implements LispInfo {
+
+ protected final boolean infoReply;
+ protected final long nonce;
+ protected final short keyId;
+ protected final short authDataLength;
+ protected final byte[] authenticationData;
+ protected final int ttl;
+ protected final byte maskLength;
+ protected final LispAfiAddress eidPrefix;
+
+ private static final int INFO_REPLY_INDEX = 3;
+ private static final int RESERVED_SKIP_LENGTH_1 = 3;
+ private static final int RESERVED_SKIP_LENGTH_2 = 1;
+
+ private static final int INFO_REQUEST_SHIFT_BIT = 4;
+
+ private static final int ENABLE_BIT = 1;
+ private static final int DISABLE_BIT = 0;
+
+ private static final int UNUSED_ZERO = 0;
+
+ /**
+ * A private constructor that protects object instantiation from external.
+ *
+ * @param infoReply info reply flag
+ * @param nonce nonce
+ * @param keyId key identifier
+ * @param authDataLength authentication data length
+ * @param authenticationData authentication data
+ * @param ttl Time-To-Live value
+ * @param maskLength EID prefix mask length
+ * @param eidPrefix EID prefix
+ */
+ protected DefaultLispInfo(boolean infoReply, long nonce, short keyId, short authDataLength,
+ byte[] authenticationData, int ttl, byte maskLength,
+ LispAfiAddress eidPrefix) {
+ this.infoReply = infoReply;
+ this.nonce = nonce;
+ this.keyId = keyId;
+ this.authDataLength = authDataLength;
+ this.authenticationData = authenticationData;
+ this.ttl = ttl;
+ this.maskLength = maskLength;
+ this.eidPrefix = eidPrefix;
+ }
+
+ @Override
+ public LispType getType() {
+ return LispType.LISP_INFO;
+ }
+
+ @Override
+ public void writeTo(ByteBuf byteBuf) {
+ // TODO: serialize LispMapRegister message
+ }
+
+ @Override
+ public Builder createBuilder() {
+ return new DefaultLispInfoRequest.DefaultInfoRequestBuilder();
+ }
+
+ @Override
+ public boolean hasInfoReply() {
+ return infoReply;
+ }
+
+ @Override
+ public long getNonce() {
+ return nonce;
+ }
+
+ @Override
+ public short getKeyId() {
+ return keyId;
+ }
+
+ @Override
+ public short getAuthDataLength() {
+ return authDataLength;
+ }
+
+ @Override
+ public byte[] getAuthenticationData() {
+ if (authenticationData != null && authenticationData.length != 0) {
+ return ImmutableByteSequence.copyFrom(authenticationData).asArray();
+ } else {
+ return new byte[0];
+ }
+ }
+
+ @Override
+ public int getTtl() {
+ return ttl;
+ }
+
+ @Override
+ public byte getMaskLength() {
+ return maskLength;
+ }
+
+ @Override
+ public LispAfiAddress getPrefix() {
+ return eidPrefix;
+ }
+
+ public static LispInfo deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException {
+
+ if (byteBuf.readerIndex() != 0) {
+ return null;
+ }
+
+ // infoReply -> 1 bit
+ boolean infoReplyFlag = ByteOperator.getBit(byteBuf.readByte(), INFO_REPLY_INDEX);
+
+ // let's skip the reserved field
+ byteBuf.skipBytes(RESERVED_SKIP_LENGTH_1);
+
+ // nonce -> 64 bits
+ long nonce = byteBuf.readLong();
+
+ // keyId -> 16 bits
+ short keyId = byteBuf.readShort();
+
+ // authenticationDataLength -> 16 bits
+ short authLength = byteBuf.readShort();
+
+ // authenticationData -> depends on the authenticationDataLength
+ byte[] authData = new byte[authLength];
+ byteBuf.readBytes(authData);
+
+ // ttl -> 32 bits
+ int ttl = byteBuf.readInt();
+
+ // let's skip the reserved field
+ byteBuf.skipBytes(RESERVED_SKIP_LENGTH_2);
+
+ // mask length -> 8 bits
+ short maskLength = byteBuf.readUnsignedByte();
+
+ LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
+
+ return new DefaultLispInfo(infoReplyFlag, nonce, keyId, authLength,
+ authData, ttl, (byte) maskLength, prefix);
+ }
+
+ public static void serialize(ByteBuf byteBuf, LispInfo message) throws LispWriterException {
+
+ // specify LISP message type
+ byte msgType = (byte) (LispType.LISP_INFO.getTypeCode() << INFO_REQUEST_SHIFT_BIT);
+
+ // info reply flag
+ byte infoReply = DISABLE_BIT;
+ if (message.hasInfoReply()) {
+ infoReply = (byte) (ENABLE_BIT << INFO_REPLY_INDEX);
+ }
+
+ byteBuf.writeByte(msgType + infoReply);
+
+ // fill zero into reserved filed
+ byteBuf.writeByte((short) UNUSED_ZERO);
+ byteBuf.writeByte((short) UNUSED_ZERO);
+ byteBuf.writeByte((short) UNUSED_ZERO);
+
+ // nonce
+ byteBuf.writeLong(message.getNonce());
+
+ // keyId
+ byteBuf.writeShort(message.getKeyId());
+
+ // authentication data length in octet
+ byteBuf.writeShort(message.getAuthDataLength());
+
+ // authentication data
+ byte[] data = message.getAuthenticationData();
+ byte[] clone;
+ if (data != null) {
+ clone = data.clone();
+ Arrays.fill(clone, (byte) UNUSED_ZERO);
+ }
+
+ byteBuf.writeBytes(data);
+
+ // TODO: need to implement MAC authentication mechanism
+
+ /// TTL
+ byteBuf.writeInt(message.getTtl());
+
+ // fill zero into reserved filed
+ byteBuf.writeByte((short) UNUSED_ZERO);
+
+ // mask length
+ byteBuf.writeByte(message.getMaskLength());
+
+ // EID prefix AFI with EID prefix
+ AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
+ afiAddressWriter.writeTo(byteBuf, message.getPrefix());
+ }
+}