/* * 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.protocols; import com.google.common.base.Objects; import io.netty.buffer.ByteBuf; import org.onlab.util.ByteOperator; 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 static com.google.common.base.MoreObjects.toStringHelper; /** * A default implementation class of LISP generic locator interface. */ public class DefaultLispGenericLocator implements LispGenericLocator { protected final byte priority; protected final byte weight; protected final byte multicastPriority; protected final byte multicastWeight; protected final boolean localLocator; protected final boolean rlocProbed; protected final boolean routed; protected final LispAfiAddress locatorAfi; private static final int LOCAL_LOCATOR_SHIFT_BIT = 2; private static final int PROBED_SHIFT_BIT = 1; private static final int ENABLE_BIT = 1; private static final int DISABLE_BIT = 0; private static final int SKIP_UNUSED_FLAG_LENGTH = 1; private static final int LOCAL_LOCATOR_INDEX = 2; private static final int RLOC_PROBED_INDEX = 1; private static final int ROUTED_INDEX = 0; /** * A private constructor that protects object instantiation from external. * * @param priority uni-cast priority * @param weight uni-cast weight * @param multicastPriority multi-cast priority * @param multicastWeight multi-cast weight * @param localLocator local locator flag * @param rlocProbed RLOC probed flag * @param routed routed flag * @param locatorAfi locator AFI */ protected DefaultLispGenericLocator(byte priority, byte weight, byte multicastPriority, byte multicastWeight, boolean localLocator, boolean rlocProbed, boolean routed, LispAfiAddress locatorAfi) { this.priority = priority; this.weight = weight; this.multicastPriority = multicastPriority; this.multicastWeight = multicastWeight; this.localLocator = localLocator; this.rlocProbed = rlocProbed; this.routed = routed; this.locatorAfi = locatorAfi; } @Override public byte getPriority() { return priority; } @Override public byte getWeight() { return weight; } @Override public byte getMulticastPriority() { return multicastPriority; } @Override public byte getMulticastWeight() { return multicastWeight; } @Override public boolean isLocalLocator() { return localLocator; } @Override public boolean isRlocProbed() { return rlocProbed; } @Override public boolean isRouted() { return routed; } @Override public LispAfiAddress getLocatorAfi() { return locatorAfi; } @Override public void writeTo(ByteBuf byteBuf) throws LispWriterException { } @Override public String toString() { return toStringHelper(this) .add("priority", priority) .add("weight", weight) .add("multi-cast priority", multicastPriority) .add("multi-cast weight", multicastWeight) .add("local locator", localLocator) .add("RLOC probed", rlocProbed) .add("routed", routed) .add("locator AFI", locatorAfi).toString(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DefaultLispGenericLocator that = (DefaultLispGenericLocator) o; return Objects.equal(priority, that.priority) && Objects.equal(weight, that.weight) && Objects.equal(multicastPriority, that.multicastPriority) && Objects.equal(multicastWeight, that.multicastWeight) && Objects.equal(localLocator, that.localLocator) && Objects.equal(rlocProbed, that.rlocProbed) && Objects.equal(routed, that.routed) && Objects.equal(locatorAfi, that.locatorAfi); } @Override public int hashCode() { return Objects.hashCode(priority, weight, multicastPriority, multicastWeight, localLocator, rlocProbed, routed, locatorAfi); } public abstract static class AbstractGenericLocatorBuilder<T> implements GenericLocatorBuilder<T> { protected byte priority; protected byte weight; protected byte multicastPriority; protected byte multicastWeight; protected boolean localLocator; protected boolean rlocProbed; protected boolean routed; protected LispAfiAddress locatorAfi; @Override public T withPriority(byte priority) { this.priority = priority; return (T) this; } @Override public T withWeight(byte weight) { this.weight = weight; return (T) this; } @Override public T withMulticastPriority(byte priority) { this.multicastPriority = priority; return (T) this; } @Override public T withMulticastWeight(byte weight) { this.multicastWeight = weight; return (T) this; } @Override public T withLocalLocator(boolean localLocator) { this.localLocator = localLocator; return (T) this; } @Override public T withRlocProbed(boolean rlocProbed) { this.rlocProbed = rlocProbed; return (T) this; } @Override public T withRouted(boolean routed) { this.routed = routed; return (T) this; } @Override public T withLocatorAfi(LispAfiAddress locatorAfi) { this.locatorAfi = locatorAfi; return (T) this; } } /** * Deserializes LispGenericLocator message portion. * * @param byteBuf byte buffer * @return LispGenericLocator * @throws LispParseError LISP message parse error * @throws LispReaderException LISP message reader exception */ public static LispGenericLocator deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException { // priority -> 8 bits byte priority = (byte) byteBuf.readUnsignedByte(); // weight -> 8 bits byte weight = (byte) byteBuf.readUnsignedByte(); // multi-cast priority -> 8 bits byte multicastPriority = (byte) byteBuf.readUnsignedByte(); // multi-cast weight -> 8 bits byte multicastWeight = (byte) byteBuf.readUnsignedByte(); // let's skip unused flags byteBuf.skipBytes(SKIP_UNUSED_FLAG_LENGTH); byte flags = byteBuf.readByte(); // local locator flag -> 1 bit boolean localLocator = ByteOperator.getBit(flags, LOCAL_LOCATOR_INDEX); // rloc probe flag -> 1 bit boolean rlocProbed = ByteOperator.getBit(flags, RLOC_PROBED_INDEX); // routed flag -> 1 bit boolean routed = ByteOperator.getBit(flags, ROUTED_INDEX); LispAfiAddress address = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf); return new DefaultLispGenericLocator(priority, weight, multicastPriority, multicastWeight, localLocator, rlocProbed, routed, address); } /** * Serializes LispGenericLocator message portion. * * @param byteBuf byte buffer * @param genericLocator generic locator * @throws LispWriterException LISP message writer exception */ public static void serialize(ByteBuf byteBuf, LispGenericLocator genericLocator) throws LispWriterException { // priority byteBuf.writeByte(genericLocator.getPriority()); // weight byteBuf.writeByte(genericLocator.getWeight()); // multicast priority byteBuf.writeByte(genericLocator.getMulticastPriority()); // multicast weight byteBuf.writeByte(genericLocator.getMulticastWeight()); // unused flags byteBuf.writeByte((short) 0); // localLocator flag short localLocator = DISABLE_BIT; if (genericLocator.isLocalLocator()) { localLocator = (byte) (ENABLE_BIT << LOCAL_LOCATOR_SHIFT_BIT); } // rlocProbed flag short probed = DISABLE_BIT; if (genericLocator.isRlocProbed()) { probed = (byte) (ENABLE_BIT << PROBED_SHIFT_BIT); } // routed flag short routed = DISABLE_BIT; if (genericLocator.isRouted()) { routed = (byte) ENABLE_BIT; } byteBuf.writeByte((byte) (localLocator + probed + routed)); // EID prefix AFI with EID prefix AfiAddressWriter afiAddressWriter = new AfiAddressWriter(); afiAddressWriter.writeTo(byteBuf, genericLocator.getLocatorAfi()); } }