blob: 74132452b82d0eeafcabeb9a96e98423964ebd38 [file] [log] [blame]
/*
* 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) throws LispWriterException {
serialize(byteBuf, this);
}
@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());
}
}