blob: 920d35640004c0c492dc79511f38776577acfcf8 [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.types.lcaf;
import io.netty.buffer.ByteBuf;
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.AddressFamilyIdentifierEnum;
import org.onosproject.lisp.msg.types.LispAddressReader;
import org.onosproject.lisp.msg.types.LispAddressWriter;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.APPLICATION_DATA;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.LIST;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.MULTICAST;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.NAT;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.NONCE;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.SEGMENT;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.SOURCE_DEST;
import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.TRAFFIC_ENGINEERING;
/**
* LISP Canonical Address Formatted address class.
* <p>
* <pre>
* {@literal
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | AFI = 16387 | Rsvd1 | Flags |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | Rsvd2 | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* }</pre>
*/
public class LispLcafAddress extends LispAfiAddress {
private static final Logger log = LoggerFactory.getLogger(LispLcafAddress.class);
private final LispCanonicalAddressFormatEnum lcafType;
private final byte reserved1;
private final byte reserved2;
private final byte flag;
private final short length;
private static final int LCAF_AFI_CODE_BYTE_LENGTH = 2;
private static final int LENGTH_FIELD_INDEX = 7;
public static final int COMMON_HEADER_SIZE = 8;
/**
* Initializes LCAF address.
*
* @param lcafType LCAF type
* @param reserved1 reserved1 field
* @param reserved2 reserved2 field
* @param flag flag field
* @param length length field
*/
protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
byte reserved1, byte reserved2, byte flag, short length) {
super(AddressFamilyIdentifierEnum.LCAF);
this.lcafType = lcafType;
this.reserved1 = reserved1;
this.reserved2 = reserved2;
this.flag = flag;
this.length = length;
}
/**
* Initializes LCAF address.
*
* @param lcafType LCAF type
* @param reserved2 reserved2 field
* @param flag flag field
* @param length length field
*/
protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
byte reserved2, byte flag, short length) {
super(AddressFamilyIdentifierEnum.LCAF);
this.lcafType = lcafType;
this.reserved2 = reserved2;
this.flag = flag;
this.length = length;
this.reserved1 = 0;
}
/**
* Initializes LCAF address.
*
* @param lcafType LCAF type
* @param reserved2 reserved2 field
* @param length length field
*/
protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
byte reserved2, short length) {
super(AddressFamilyIdentifierEnum.LCAF);
this.lcafType = lcafType;
this.reserved2 = reserved2;
this.length = length;
this.reserved1 = 0;
this.flag = 0;
}
/**
* Initializes LCAF address.
*
* @param lcafType LCAF type
* @param reserved2 reserved2 field
*/
protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, byte reserved2) {
super(AddressFamilyIdentifierEnum.LCAF);
this.lcafType = lcafType;
this.reserved2 = reserved2;
this.reserved1 = 0;
this.flag = 0;
this.length = 0;
}
/**
* Initializes LCAF address.
*
* @param lcafType LCAF type
* @param length length field
*/
protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, short length) {
super(AddressFamilyIdentifierEnum.LCAF);
this.lcafType = lcafType;
this.reserved1 = 0;
this.reserved2 = 0;
this.flag = 0;
this.length = length;
}
/**
* Initializes LCAF address.
*
* @param lcafType LCAF type
*/
protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType) {
super(AddressFamilyIdentifierEnum.LCAF);
this.lcafType = lcafType;
this.reserved1 = 0;
this.reserved2 = 0;
this.flag = 0;
this.length = 0;
}
/**
* Obtains LCAF type.
*
* @return LCAF type
*/
public LispCanonicalAddressFormatEnum getType() {
return lcafType;
}
/**
* Obtains LCAF reserved1 value.
*
* @return LCAF reserved1 value
*/
public byte getReserved1() {
return reserved1;
}
/**
* Obtains LCAF reserved2 value.
*
* @return LCAF reserved2 value
*/
public byte getReserved2() {
return reserved2;
}
/**
* Obtains LCAF flag value.
*
* @return LCAF flag value
*/
public byte getFlag() {
return flag;
}
/**
* Obtains LCAF length value.
*
* @return LCAF length value
*/
public short getLength() {
return length;
}
/**
* Deserializes common fields from byte buffer.
*
* @param byteBuf byte buffer
* @return LispLcafAddress with filled common data fields
*/
public static LispLcafAddress deserializeCommon(ByteBuf byteBuf) {
// let's skip first and second two bytes
,
// because it represents LCAF AFI code
byteBuf.skipBytes(LCAF_AFI_CODE_BYTE_LENGTH);
// reserved1 -> 8 bits
byte reserved1 = (byte) byteBuf.readUnsignedByte();
// flags -> 8 bits
byte flag = (byte) byteBuf.readUnsignedByte();
// LCAF type -> 8 bits
byte lcafType = (byte) byteBuf.readUnsignedByte();
// reserved2 -> 8bits
byte reserved2 = (byte) byteBuf.readUnsignedByte();
// length -> 16 bits
short length = (short) byteBuf.readUnsignedShort();
return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
reserved1, reserved2, flag, length);
}
/**
* Updates the header length field value based on the size of LISP header.
*
* @param lcafIndex the index of LCAF address, because LCAF address is
* contained inside LISP control message, so to correctly
* find the right LCAF length index, we need to know the
* absolute lcaf index inside LISP control message byte buf
* @param byteBuf netty byte buffer
*/
public static void updateLength(int lcafIndex, ByteBuf byteBuf) {
byteBuf.setByte(lcafIndex + LENGTH_FIELD_INDEX,
byteBuf.writerIndex() - COMMON_HEADER_SIZE - lcafIndex);
}
/**
* Serializes common fields to byte buffer.
*
* @param byteBuf byte buffer
* @param address LISP LCAF address instance
*/
public static void serializeCommon(ByteBuf byteBuf, LispLcafAddress address) {
byteBuf.writeShort(AddressFamilyIdentifierEnum.LCAF.getIanaCode());
byteBuf.writeByte(address.getReserved1());
byteBuf.writeByte(address.getFlag());
byteBuf.writeByte(address.getType().getLispCode());
byteBuf.writeByte(address.getReserved2());
byteBuf.writeShort(address.getLength());
}
@Override
public int hashCode() {
return Objects.hash(lcafType, reserved1, reserved2, flag, length);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LispLcafAddress) {
final LispLcafAddress other = (LispLcafAddress) obj;
return Objects.equals(this.lcafType, other.lcafType) &&
Objects.equals(this.reserved1, other.reserved1) &&
Objects.equals(this.reserved2, other.reserved2) &&
Objects.equals(this.flag, other.flag) &&
Objects.equals(this.length, other.length);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this)
.add("lcafType", lcafType)
.add("reserved1", reserved1)
.add("reserved2", reserved2)
.add("flag", flag)
.add("length", length)
.toString();
}
protected static class LcafAddressBuilder<T> {
protected byte reserved1;
protected byte flag;
protected byte lcafType;
protected byte reserved2;
protected short length;
/**
* Sets reserved1 value.
*
* @param reserved1 reserved1 value
* @return LcafAddressBuilder object
*/
public T withReserved1(byte reserved1) {
this.reserved1 = reserved1;
return (T) this;
}
/**
* Sets flag.
*
* @param flag flag boolean
* @return LcafAddressBuilder object
*/
public T withFlag(byte flag) {
this.flag = flag;
return (T) this;
}
/**
* Sets LCAF type.
*
* @param lcafType LCAF type
* @return LcafAddressBuilder object
*/
public T withLcafType(byte lcafType) {
this.lcafType = lcafType;
return (T) this;
}
/**
* Sets reserved2 value.
*
* @param reserved2 reserved2 value
* @return LcafAddressBuilder object
*/
public T withReserved2(byte reserved2) {
this.reserved2 = reserved2;
return (T) this;
}
/**
* Sets length value.
*
* @param length length value
* @return LcafAddressBuilder object
*/
public T withLength(short length) {
this.length = length;
return (T) this;
}
/**
* Builds LispLcafAddress object.
*
* @return LispLcafAddress instance
*/
public LispLcafAddress build() {
return new LispLcafAddress(LispCanonicalAddressFormatEnum
.valueOf(lcafType),
reserved1, reserved2, flag, length);
}
}
/**
* LISP LCAF reader class.
*/
public static class LcafAddressReader
implements LispAddressReader<LispLcafAddress> {
private static final int LCAF_TYPE_FIELD_INDEX = 4;
@Override
public LispLcafAddress readFrom(ByteBuf byteBuf)
throws LispParseError, LispReaderException {
int index = byteBuf.readerIndex();
// LCAF type -> 8 bits
byte lcafType = (byte) byteBuf.getUnsignedByte(index + LCAF_TYPE_FIELD_INDEX);
if (lcafType == APPLICATION_DATA.getLispCode()) {
return new LispAppDataLcafAddress.AppDataLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == NAT.getLispCode()) {
return new LispNatLcafAddress.NatLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == LIST.getLispCode()) {
return new LispListLcafAddress.ListLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == SEGMENT.getLispCode()) {
return new LispSegmentLcafAddress.SegmentLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == NONCE.getLispCode()) {
return new LispNonceLcafAddress.NonceLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == MULTICAST.getLispCode()) {
return new LispMulticastLcafAddress.MulticastLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == SOURCE_DEST.getLispCode()) {
return new LispSourceDestLcafAddress.SourceDestLcafAddressReader().readFrom(byteBuf);
}
if (lcafType == TRAFFIC_ENGINEERING.getLispCode()) {
return new LispTeLcafAddress.TeLcafAddressReader().readFrom(byteBuf);
}
log.warn("Unsupported LCAF type, please specify a correct LCAF type");
return null;
}
}
/**
* LISP LCAF address writer class.
*/
public static class LcafAddressWriter
implements LispAddressWriter<LispLcafAddress> {
@Override
public void writeTo(ByteBuf byteBuf, LispLcafAddress address)
throws LispWriterException {
switch (address.getType()) {
case APPLICATION_DATA:
new LispAppDataLcafAddress.AppDataLcafAddressWriter().writeTo(byteBuf,
(LispAppDataLcafAddress) address);
break;
case NAT:
new LispNatLcafAddress.NatLcafAddressWriter().writeTo(byteBuf,
(LispNatLcafAddress) address);
break;
case LIST:
new LispListLcafAddress.ListLcafAddressWriter().writeTo(byteBuf,
(LispListLcafAddress) address);
break;
case SEGMENT:
new LispSegmentLcafAddress.SegmentLcafAddressWriter().writeTo(byteBuf,
(LispSegmentLcafAddress) address);
break;
case NONCE:
new LispNonceLcafAddress.NonceLcafAddressWriter().writeTo(byteBuf,
(LispNonceLcafAddress) address);
break;
case MULTICAST:
new LispMulticastLcafAddress.MulticastLcafAddressWriter().writeTo(byteBuf,
(LispMulticastLcafAddress) address);
break;
case SOURCE_DEST:
new LispSourceDestLcafAddress.SourceDestLcafAddressWriter().writeTo(byteBuf,
(LispSourceDestLcafAddress) address);
break;
case TRAFFIC_ENGINEERING:
new LispTeLcafAddress.TeLcafAddressWriter().writeTo(byteBuf,
(LispTeLcafAddress) address);
break;
default:
log.warn("Unsupported LCAF type, please specify a correct LCAF type");
break;
}
}
}
}