/* * 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.LispAddressReader; import org.onosproject.lisp.msg.types.LispAddressWriter; import org.onosproject.lisp.msg.types.LispAfiAddress; import java.util.Objects; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; /** * Instance ID type LCAF address class. * <p> * Instance ID type is defined in draft-ietf-lisp-lcaf-22 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-8 * * <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 = 2 | IID mask-len | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Instance ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * }</pre> */ public final class LispSegmentLcafAddress extends LispLcafAddress { private final LispAfiAddress address; private final int instanceId; /** * Initializes segment type LCAF address. * * @param idMaskLength Id mask length * @param instanceId instance id * @param address address */ private LispSegmentLcafAddress(byte idMaskLength, int instanceId, LispAfiAddress address) { super(LispCanonicalAddressFormatEnum.SEGMENT, idMaskLength); this.address = address; this.instanceId = instanceId; } /** * Initializes segment type LCAF address. * * @param reserved1 reserved1 * @param idMaskLength ID mask length * @param flag flag * @param length length * @param instanceId instance id * @param address address */ private LispSegmentLcafAddress(byte reserved1, byte idMaskLength, byte flag, short length, int instanceId, LispAfiAddress address) { super(LispCanonicalAddressFormatEnum.SEGMENT, reserved1, idMaskLength, flag, length); this.address = address; this.instanceId = instanceId; } /** * Obtains address. * * @return address */ public LispAfiAddress getAddress() { return address; } /** * Obtains instance id. * * @return instance id */ public int getInstanceId() { return instanceId; } /** * Obtains id mask length. * * @return id mask length */ public byte getIdMaskLength() { return getReserved2(); } @Override public int hashCode() { return Objects.hash(address, instanceId, getReserved2()); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof LispSegmentLcafAddress) { final LispSegmentLcafAddress other = (LispSegmentLcafAddress) obj; return Objects.equals(this.address, other.address) && Objects.equals(this.instanceId, other.instanceId) && Objects.equals(this.getReserved2(), other.getReserved2()); } return false; } @Override public String toString() { return toStringHelper(this) .add("address", address) .add("instanceId", instanceId) .add("idMaskLength", getReserved2()) .toString(); } public static final class SegmentAddressBuilder extends LcafAddressBuilder<SegmentAddressBuilder> { private byte idMaskLength; private LispAfiAddress address; private int instanceId; /** * Sets identifier mask length. * * @param idMaskLength identifier mask length * @return SegmentAddressBuilder object */ public SegmentAddressBuilder withIdMaskLength(byte idMaskLength) { this.idMaskLength = idMaskLength; return this; } /** * Sets instance identifer. * * @param instanceId instance identifier * @return SegmentAddressBuilder object */ public SegmentAddressBuilder withInstanceId(int instanceId) { this.instanceId = instanceId; return this; } /** * Sets AFI address. * * @param address AFI address * @return SegmentAddressBuilder object */ public SegmentAddressBuilder withAddress(LispAfiAddress address) { this.address = address; return this; } /** * Builds LispSegmentLcafAddress instance. * * @return LispSegmentLcafAddress instance */ public LispSegmentLcafAddress build() { checkNotNull(address, "Must specify an address"); return new LispSegmentLcafAddress(reserved1, idMaskLength, flag, length, instanceId, address); } } /** * Segment LCAF address reader class. */ public static class SegmentLcafAddressReader implements LispAddressReader<LispSegmentLcafAddress> { @Override public LispSegmentLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException { LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf); byte idMaskLength = lcafAddress.getReserved2(); int instanceId = (int) byteBuf.readUnsignedInt(); LispAfiAddress address = new AfiAddressReader().readFrom(byteBuf); return new SegmentAddressBuilder() .withIdMaskLength(idMaskLength) .withInstanceId(instanceId) .withAddress(address) .build(); } } /** * Segment LCAF address writer class. */ public static class SegmentLcafAddressWriter implements LispAddressWriter<LispSegmentLcafAddress> { @Override public void writeTo(ByteBuf byteBuf, LispSegmentLcafAddress address) throws LispWriterException { int lcafIndex = byteBuf.writerIndex(); LispLcafAddress.serializeCommon(byteBuf, address); byteBuf.writeInt(address.getInstanceId()); new LispAfiAddress.AfiAddressWriter().writeTo(byteBuf, address.getAddress()); LispLcafAddress.updateLength(lcafIndex, byteBuf); } } }