/* * Copyright 2017-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; /** * Nonce locator data type LCAF address class. * <p> * Nonce locator data type is defined in draft-ietf-lisp-lcaf-22 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-32 * <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 = 8 | Rsvd2 | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * }</pre> */ public final class LispNonceLcafAddress extends LispLcafAddress { private final int nonce; private final LispAfiAddress address; /** * Initializes nonce locator data type LCAF address. * * @param nonce nonce * @param address address */ private LispNonceLcafAddress(int nonce, LispAfiAddress address) { super(LispCanonicalAddressFormatEnum.NONCE); this.nonce = nonce; this.address = address; } /** * Obtains nonce. * * @return nonce */ public int getNonce() { return nonce; } /** * Obtains address. * * @return address */ public LispAfiAddress getAddress() { return address; } @Override public int hashCode() { return Objects.hash(nonce, address); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof LispNonceLcafAddress) { final LispNonceLcafAddress other = (LispNonceLcafAddress) obj; return Objects.equals(this.nonce, other.nonce) && Objects.equals(this.address, other.address); } return false; } @Override public String toString() { return toStringHelper(this) .add("nonce", nonce) .add("address", address) .toString(); } public static final class NonceAddressBuilder extends LcafAddressBuilder<NonceAddressBuilder> { private int nonce; private LispAfiAddress address; /** * Sets nonce. * * @param nonce nonce * @return NonceAddressBuilder object */ public NonceAddressBuilder withNonce(int nonce) { this.nonce = nonce; return this; } /** * Sets address. * * @param address address * @return NonceAddressBuilder object */ public NonceAddressBuilder withAddress(LispAfiAddress address) { this.address = address; return this; } /** * Builds LispNonceLcafAddress instance. * * @return LispNonceLcafAddress instance */ public LispNonceLcafAddress build() { checkNotNull(address, "Must specify an address"); return new LispNonceLcafAddress(nonce, address); } } /** * Nonce LCAF address reader class. */ public static class NonceLcafAddressReader implements LispAddressReader<LispNonceLcafAddress> { private static final int NONCE_SHIFT_BIT = 16; private static final int RESERVED_SKIP_LENGTH = 1; @Override public LispNonceLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException { deserializeCommon(byteBuf); byteBuf.skipBytes(RESERVED_SKIP_LENGTH); // nonce -> 24 bits int nonceFirst = byteBuf.readShort() << NONCE_SHIFT_BIT; int nonceSecond = byteBuf.readInt(); int nonce = nonceFirst + nonceSecond; LispAfiAddress address = new AfiAddressReader().readFrom(byteBuf); return new NonceAddressBuilder() .withNonce(nonce) .withAddress(address) .build(); } } /** * Nonce LCAF address writer class. */ public static class NonceLcafAddressWriter implements LispAddressWriter<LispNonceLcafAddress> { private static final int UNUSED_ZERO = 0; private static final int NONCE_SHIFT_BIT = 16; @Override public void writeTo(ByteBuf byteBuf, LispNonceLcafAddress address) throws LispWriterException { int lcafIndex = byteBuf.writerIndex(); LispLcafAddress.serializeCommon(byteBuf, address); // reserved field byteBuf.writeByte(UNUSED_ZERO); // nonce field int nonceFirst = address.getNonce() >> NONCE_SHIFT_BIT; byteBuf.writeShort((short) nonceFirst); int nonceSecond = address.getNonce() - (nonceFirst << NONCE_SHIFT_BIT); byteBuf.writeInt(nonceSecond); // address AfiAddressWriter writer = new AfiAddressWriter(); writer.writeTo(byteBuf, address.getAddress()); LispLcafAddress.updateLength(lcafIndex, byteBuf); } } }