/* * 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.GEO_COORDINATE; 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 == GEO_COORDINATE.getLispCode()) { return new LispGeoCoordinateLcafAddress.GeoCoordinateLcafAddressReader().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 GEO_COORDINATE: new LispGeoCoordinateLcafAddress.GeoCoordinateLcafAddressWriter().writeTo(byteBuf, (LispGeoCoordinateLcafAddress) 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; } } } }