Jian Li
Committed by Gerrit Code Review

[ONOS-4718] Initial implementation of LISP control msg deserializer

- Add LispLocatorRecord interface along with
  DefaultLispLocatorRecord class and unit test class
- Add deserialization logic for four LISP control message classes
  and two auxiliary classes
- Add ByteOperator utility to ease the bit access and manipulation
  for byte data type

Change-Id: I68edf6877a0ebb52260296fc556e0690b795a845
Showing 20 changed files with 972 additions and 38 deletions
/*
* 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.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.types.LispAfiAddress;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Default implementation of LispLocatorRecord.
*/
public final class DefaultLispLocatorRecord implements LispLocatorRecord {
private final byte priority;
private final byte weight;
private final byte multicastPriority;
private final byte multicastWeight;
private final boolean localLocator;
private final boolean rlocProbed;
private final boolean routed;
private final LispAfiAddress locatorAfi;
/**
* 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
*/
private DefaultLispLocatorRecord(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) {
}
@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;
}
DefaultLispLocatorRecord that = (DefaultLispLocatorRecord) 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 static final class DefaultLocatorRecordBuilder implements LocatorRecordBuilder {
private byte priority;
private byte weight;
private byte multicastPriority;
private byte multicastWeight;
private boolean localLocator;
private boolean rlocProbed;
private boolean routed;
private LispAfiAddress locatorAfi;
@Override
public LocatorRecordBuilder withPriority(byte priority) {
this.priority = priority;
return this;
}
@Override
public LocatorRecordBuilder withWeight(byte weight) {
this.weight = weight;
return this;
}
@Override
public LocatorRecordBuilder withMulticastPriority(byte priority) {
this.multicastPriority = priority;
return this;
}
@Override
public LocatorRecordBuilder withMulticastWeight(byte weight) {
this.multicastWeight = weight;
return this;
}
@Override
public LocatorRecordBuilder withLocalLocator(boolean localLocator) {
this.localLocator = localLocator;
return this;
}
@Override
public LocatorRecordBuilder withRlocProbed(boolean rlocProbed) {
this.rlocProbed = rlocProbed;
return this;
}
@Override
public LocatorRecordBuilder withRouted(boolean routed) {
this.routed = routed;
return this;
}
@Override
public LocatorRecordBuilder withLocatorAfi(LispAfiAddress locatorAfi) {
this.locatorAfi = locatorAfi;
return this;
}
@Override
public LispLocatorRecord build() {
return new DefaultLispLocatorRecord(priority, weight, multicastPriority,
multicastWeight, localLocator, rlocProbed, routed, locatorAfi);
}
}
/**
* A LISP message reader for LocatorRecord portion.
*/
public static final class LocatorRecordReader implements LispMessageReader<LispLocatorRecord> {
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;
@Override
public LispLocatorRecord readFrom(ByteBuf byteBuf) throws LispParseError {
// 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);
// TODO: de-serialize ITR-RLOC AFI and address
return new DefaultLocatorRecordBuilder()
.withPriority(priority)
.withWeight(weight)
.withMulticastPriority(multicastPriority)
.withMulticastWeight(multicastWeight)
.withLocalLocator(localLocator)
.withRlocProbed(rlocProbed)
.withRouted(routed)
.build();
}
}
}
......@@ -131,7 +131,7 @@ public final class DefaultLispMapNotify implements LispMapNotify {
private short keyId;
private byte[] authenticationData;
private byte recordCount;
private List<LispMapRecord> mapRecords = Lists.newArrayList();
private List<LispMapRecord> mapRecords;
@Override
public LispType getType() {
......@@ -163,8 +163,8 @@ public final class DefaultLispMapNotify implements LispMapNotify {
}
@Override
public NotifyBuilder addRecord(LispMapRecord record) {
this.mapRecords.add(record);
public NotifyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
this.mapRecords = ImmutableList.copyOf(mapRecords);
return this;
}
......@@ -180,9 +180,46 @@ public final class DefaultLispMapNotify implements LispMapNotify {
*/
private static class NotifyReader implements LispMessageReader<LispMapNotify> {
private static final int RESERVED_SKIP_LENGTH = 3;
@Override
public LispMapNotify readFrom(ByteBuf byteBuf) throws LispParseError {
if (byteBuf.readerIndex() != 0) {
return null;
}
// skip first three bytes as they represent type and reserved fields
byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
// record count -> 8 bits
byte recordCount = (byte) byteBuf.readUnsignedByte();
// nonce -> 64 bits
long nonce = byteBuf.readLong();
// keyId -> 16 bits
short keyId = byteBuf.readShort();
// authenticationDataLength -> 16 bits
short authLength = byteBuf.readShort();
// authenticationData -> depends on the authenticationDataLength
byte[] authData = new byte[authLength];
byteBuf.readBytes(authData);
List<LispMapRecord> mapRecords = Lists.newArrayList();
for (int i = 0; i < recordCount; i++) {
mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
}
return new DefaultNotifyBuilder()
.withRecordCount(recordCount)
.withNonce(nonce)
.withKeyId(keyId)
.withAuthenticationData(authData)
.withMapRecords(mapRecords)
.build();
}
}
}
......
......@@ -16,10 +16,15 @@
package org.onosproject.lisp.msg.protocols;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import org.onlab.util.ByteOperator;
import org.onosproject.lisp.msg.exceptions.LispParseError;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import java.util.List;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
......@@ -34,6 +39,7 @@ public final class DefaultLispMapRecord implements LispMapRecord {
private final boolean authoritative;
private final short mapVersionNumber;
private final LispAfiAddress eidPrefixAfi;
private final List<LispLocatorRecord> locatorRecords;
/**
* A private constructor that protects object instantiation from external.
......@@ -48,7 +54,8 @@ public final class DefaultLispMapRecord implements LispMapRecord {
*/
private DefaultLispMapRecord(int recordTtl, int locatorCount, byte maskLength,
LispMapReplyAction action, boolean authoritative,
short mapVersionNumber, LispAfiAddress eidPrefixAfi) {
short mapVersionNumber, LispAfiAddress eidPrefixAfi,
List<LispLocatorRecord> locatorRecords) {
this.recordTtl = recordTtl;
this.locatorCount = locatorCount;
this.maskLength = maskLength;
......@@ -56,6 +63,7 @@ public final class DefaultLispMapRecord implements LispMapRecord {
this.authoritative = authoritative;
this.mapVersionNumber = mapVersionNumber;
this.eidPrefixAfi = eidPrefixAfi;
this.locatorRecords = locatorRecords;
}
@Override
......@@ -94,6 +102,16 @@ public final class DefaultLispMapRecord implements LispMapRecord {
}
@Override
public List<LispLocatorRecord> getLocators() {
return ImmutableList.copyOf(locatorRecords);
}
@Override
public void writeTo(ByteBuf byteBuf) {
}
@Override
public String toString() {
return toStringHelper(this)
.add("record TTL", recordTtl)
......@@ -102,7 +120,9 @@ public final class DefaultLispMapRecord implements LispMapRecord {
.add("action", action)
.add("authoritative", authoritative)
.add("mapVersionNumber", mapVersionNumber)
.add("EID prefix AFI address", eidPrefixAfi).toString();
.add("EID prefix AFI address", eidPrefixAfi)
.add("locator records", locatorRecords).toString();
}
@Override
......@@ -120,13 +140,14 @@ public final class DefaultLispMapRecord implements LispMapRecord {
Objects.equal(action, that.action) &&
Objects.equal(authoritative, that.authoritative) &&
Objects.equal(mapVersionNumber, that.mapVersionNumber) &&
Objects.equal(eidPrefixAfi, that.eidPrefixAfi);
Objects.equal(eidPrefixAfi, that.eidPrefixAfi) &&
Objects.equal(locatorRecords, that.locatorRecords);
}
@Override
public int hashCode() {
return Objects.hashCode(recordTtl, locatorCount, maskLength, action,
authoritative, mapVersionNumber, eidPrefixAfi);
authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
}
public static final class DefaultMapRecordBuilder implements MapRecordBuilder {
......@@ -138,6 +159,7 @@ public final class DefaultLispMapRecord implements LispMapRecord {
private boolean authoritative;
private short mapVersionNumber;
private LispAfiAddress eidPrefixAfi;
private List<LispLocatorRecord> locatorRecords;
@Override
public MapRecordBuilder withRecordTtl(int recordTtl) {
......@@ -182,20 +204,66 @@ public final class DefaultLispMapRecord implements LispMapRecord {
}
@Override
public MapRecordBuilder withLocators(List<LispLocatorRecord> records) {
this.locatorRecords = ImmutableList.copyOf(records);
return this;
}
@Override
public LispMapRecord build() {
return new DefaultLispMapRecord(recordTtl, locatorCount, maskLength,
action, authoritative, mapVersionNumber, eidPrefixAfi);
action, authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
}
}
/**
* A private LISP message reader for MapRecord portion.
* A LISP message reader for MapRecord portion.
*/
private static class RecordReader implements LispMessageReader<LispMapRecord> {
public static final class MapRecordReader implements LispMessageReader<LispMapRecord> {
private static final int AUTHORITATIVE_INDEX = 4;
private static final int RESERVED_SKIP_LENGTH = 1;
@Override
public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError {
return null;
// Record TTL -> 32 bits
int recordTtl = byteBuf.readInt();
// Locator count -> 8 bits
int locatorCount = byteBuf.readUnsignedShort();
// EID mask length -> 8 bits
byte maskLength = (byte) byteBuf.readUnsignedByte();
// TODO: need to de-serialize LispMapReplyAction
byte actionWithFlag = byteBuf.readByte();
// authoritative flag -> 1 bit
boolean authoritative = ByteOperator.getBit(actionWithFlag, AUTHORITATIVE_INDEX);
// let's skip the reserved field
byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
// Map version number -> 12 bits, we treat Rsvd field is all zero
short mapVersionNumber = (short) byteBuf.readUnsignedShort();
// TODO: need to de-serialize EID AFI address
List<LispLocatorRecord> locators = Lists.newArrayList();
for (int i = 0; i < locatorCount; i++) {
locators.add(new DefaultLispLocatorRecord.LocatorRecordReader().readFrom(byteBuf));
}
return new DefaultMapRecordBuilder()
.withRecordTtl(recordTtl)
.withLocatorCount(locatorCount)
.withMaskLength(maskLength)
.withAuthoritative(authoritative)
.withMapVersionNumber(mapVersionNumber)
.withLocators(locators)
.build();
}
}
}
......
......@@ -19,6 +19,7 @@ import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import org.onlab.util.ByteOperator;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.lisp.msg.exceptions.LispParseError;
......@@ -155,7 +156,7 @@ public final class DefaultLispMapRegister implements LispMapRegister {
private short keyId;
private byte[] authenticationData;
private byte recordCount;
private final List<LispMapRecord> mapRecords = Lists.newArrayList();
private List<LispMapRecord> mapRecords;
private boolean proxyMapReply;
private boolean wantMapNotify;
......@@ -201,8 +202,8 @@ public final class DefaultLispMapRegister implements LispMapRegister {
}
@Override
public RegisterBuilder addRecord(LispMapRecord record) {
this.mapRecords.add(record);
public RegisterBuilder withMapRecords(List<LispMapRecord> mapRecords) {
this.mapRecords = ImmutableList.copyOf(mapRecords);
return this;
}
......@@ -218,9 +219,58 @@ public final class DefaultLispMapRegister implements LispMapRegister {
*/
private static class RegisterReader implements LispMessageReader<LispMapRegister> {
private static final int PROXY_MAP_REPLY_INDEX = 3;
private static final int WANT_MAP_NOTIFY_INDEX = 0;
private static final int RESERVED_SKIP_LENGTH = 1;
@Override
public LispMapRegister readFrom(ByteBuf byteBuf) throws LispParseError {
if (byteBuf.readerIndex() != 0) {
return null;
}
// proxyMapReply -> 1 bit
boolean proxyMapReplyFlag = ByteOperator.getBit(byteBuf.readByte(), PROXY_MAP_REPLY_INDEX);
// let's skip the reserved field
byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
byte reservedWithFlag = byteBuf.readByte();
// wantMapReply -> 1 bit
boolean wantMapNotifyFlag = ByteOperator.getBit(reservedWithFlag, WANT_MAP_NOTIFY_INDEX);
// record count -> 8 bits
byte recordCount = (byte) byteBuf.readUnsignedByte();
// nonce -> 64 bits
long nonce = byteBuf.readLong();
// keyId -> 16 bits
short keyId = byteBuf.readShort();
// authenticationDataLength -> 16 bits
short authLength = byteBuf.readShort();
// authenticationData -> depends on the authenticationDataLength
byte[] authData = new byte[authLength];
byteBuf.readBytes(authData);
List<LispMapRecord> mapRecords = Lists.newArrayList();
for (int i = 0; i < recordCount; i++) {
mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
}
return new DefaultRegisterBuilder()
.withIsProxyMapReply(proxyMapReplyFlag)
.withIsWantMapNotify(wantMapNotifyFlag)
.withRecordCount(recordCount)
.withNonce(nonce)
.withKeyId(keyId)
.withAuthenticationData(authData)
.withMapRecords(mapRecords)
.build();
}
}
}
......
......@@ -17,6 +17,7 @@ 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 static com.google.common.base.MoreObjects.toStringHelper;
......@@ -176,9 +177,47 @@ public final class DefaultLispMapReply implements LispMapReply {
*/
private static class ReplyReader implements LispMessageReader<LispMapReply> {
private static final int PROBE_INDEX = 3;
private static final int ETR_INDEX = 2;
private static final int SECURITY_INDEX = 1;
private static final int RESERVED_SKIP_LENGTH = 2;
@Override
public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError {
if (byteBuf.readerIndex() != 0) {
return null;
}
byte typeWithFlags = byteBuf.readByte();
// probe -> 1 bit
boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
// etr -> 1bit
boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);
// security -> 1 bit
boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);
// skip two bytes as they represent reserved fields
byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
// record count -> 8 bits
byte recordCount = (byte) byteBuf.readUnsignedByte();
// nonce -> 64 bits
long nonce = byteBuf.readLong();
// TODO: need to de-serialize EID-RLOC records
return new DefaultReplyBuilder()
.withIsProbe(probe)
.withIsEtr(etr)
.withIsSecurity(security)
.withRecordCount(recordCount)
.withNonce(nonce)
.build();
}
}
}
......
......@@ -19,6 +19,7 @@ import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import org.onlab.util.ByteOperator;
import org.onosproject.lisp.msg.exceptions.LispParseError;
import org.onosproject.lisp.msg.types.LispAfiAddress;
......@@ -227,7 +228,6 @@ public final class DefaultLispMapRequest implements LispMapRequest {
return this;
}
@Override
public RequestBuilder withIsSmr(boolean smr) {
this.smr = smr;
......@@ -265,14 +265,14 @@ public final class DefaultLispMapRequest implements LispMapRequest {
}
@Override
public RequestBuilder addItrRloc(LispAfiAddress itrRloc) {
this.itrRlocs.add(itrRloc);
public RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs) {
this.itrRlocs = ImmutableList.copyOf(itrRlocs);
return this;
}
@Override
public RequestBuilder addEidRecord(LispEidRecord record) {
this.eidRecords.add(record);
public RequestBuilder withEidRecords(List<LispEidRecord> records) {
this.eidRecords = ImmutableList.copyOf(records);
return this;
}
......@@ -288,9 +288,69 @@ public final class DefaultLispMapRequest implements LispMapRequest {
*/
private static class RequestReader implements LispMessageReader<LispMapRequest> {
private static final int AUTHORITATIVE_INDEX = 3;
private static final int MAP_DATA_PRESENT_INDEX = 2;
private static final int PROBE_INDEX = 1;
private static final int SMR_INDEX = 0;
private static final int PITR_INDEX = 7;
private static final int SMR_INVOKED_INDEX = 6;
@Override
public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError {
if (byteBuf.readerIndex() != 0) {
return null;
}
byte typeWithFlags = byteBuf.readByte();
// authoritative -> 1 bit
boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);
// mapDataPresent -> 1 bit
boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);
// probe -> 1 bit
boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
// smr -> 1 bit
boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);
byte reservedWithFlags = byteBuf.readByte();
// pitr -> 1 bit
boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);
// smrInvoked -> 1 bit
boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);
// let's skip reserved field, only obtains ITR counter value
// assume that first 3 bits are all set as 0,
// remain 5 bits represent Itr Rloc Counter (IRC)
int irc = byteBuf.readUnsignedShort();
// record count -> 8 bits
int recordCount = byteBuf.readUnsignedShort();
// nonce -> 64 bits
long nonce = byteBuf.readLong();
// TODO: de-serialize source EID AFI and address
// TODO: de-serialize ITR-RLOC AFI and address
// TODO: de-serialize EID-RECORD
return new DefaultRequestBuilder()
.withIsAuthoritative(authoritative)
.withIsMapDataPresent(mapDataPresent)
.withIsProbe(probe)
.withIsSmr(smr)
.withIsPitr(pitr)
.withIsSmrInvoked(smrInvoked)
.withNonce(nonce)
.withRecordCount((byte) recordCount)
.build();
}
}
}
......
......@@ -61,9 +61,20 @@ public final class LispEidRecord {
*/
private static class EidRecordReader implements LispMessageReader<LispEidRecord> {
private static final int RESERVED_SKIP_LENGTH = 1;
@Override
public LispEidRecord readFrom(ByteBuf byteBuf) throws LispParseError {
return null;
// let's skip the reserved field
byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
short maskLength = (short) byteBuf.readUnsignedShort();
// TODO: need to de-serialize AFI address
LispAfiAddress prefix = null;
return new LispEidRecord((byte) maskLength, prefix);
}
}
}
......
/*
* 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.protocols;
import io.netty.buffer.ByteBuf;
import org.onosproject.lisp.msg.types.LispAfiAddress;
/**
* LISP locator record section which is part of LISP map record.
*/
public interface LispLocatorRecord {
/**
* Obtains priority value.
*
* @return priority value
*/
byte getPriority();
/**
* Obtains weight value.
*
* @return weight value
*/
byte getWeight();
/**
* Obtains multi-cast priority value.
*
* @return multi-cast priority value
*/
byte getMulticastPriority();
/**
* Obtains multi-cast weight value.
*
* @return multi-cast weight value
*/
byte getMulticastWeight();
/**
* Obtains local locator flag.
*
* @return local locator flag
*/
boolean isLocalLocator();
/**
* Obtains RLOC probed flag.
*
* @return RLOC probed flag
*/
boolean isRlocProbed();
/**
* Obtains routed flag.
*
* @return routed flag
*/
boolean isRouted();
/**
* Obtains locator AFI.
*
* @return locator AFI
*/
LispAfiAddress getLocatorAfi();
/**
* Writes LISP message object into communication channel.
*
* @param byteBuf byte buffer
*/
void writeTo(ByteBuf byteBuf);
/**
* A builder of LISP locator record.
*/
interface LocatorRecordBuilder {
/**
* Sets priority value.
*
* @param priority priority
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withPriority(byte priority);
/**
* Sets weight value.
*
* @param weight weight
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withWeight(byte weight);
/**
* Sets multi-cast priority value.
*
* @param priority priority
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withMulticastPriority(byte priority);
/**
* Sets multi-cast weight value.
*
* @param weight weight
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withMulticastWeight(byte weight);
/**
* Sets local locator flag.
*
* @param localLocator local locator flag
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withLocalLocator(boolean localLocator);
/**
* Sets RLOC probed flag.
*
* @param rlocProbed RLOC probed flag
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withRlocProbed(boolean rlocProbed);
/**
* Sets routed flag.
*
* @param routed routed flag
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withRouted(boolean routed);
/**
* Sets locator AFI.
*
* @param locatorAfi locator AFI
* @return LocatorRecordBuilder object
*/
LocatorRecordBuilder withLocatorAfi(LispAfiAddress locatorAfi);
/**
* Builds locator record.
*
* @return locator record instance
*/
LispLocatorRecord build();
}
}
......@@ -129,12 +129,12 @@ public interface LispMapNotify extends LispMessage {
NotifyBuilder withAuthenticationData(byte[] authenticationData);
/**
* Adds a new record to record list.
* Sets a collection of map records.
*
* @param record record
* @return NotifyBuilder object
* @param mapRecords a collection of map records
* @return RegisterBuilder object
*/
NotifyBuilder addRecord(LispMapRecord record);
NotifyBuilder withMapRecords(List<LispMapRecord> mapRecords);
/**
* Builds LISP map notify message.
......
......@@ -15,8 +15,11 @@
*/
package org.onosproject.lisp.msg.protocols;
import io.netty.buffer.ByteBuf;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import java.util.List;
/**
* LISP record section which is part of LISP map register message.
*/
......@@ -72,6 +75,20 @@ public interface LispMapRecord {
LispAfiAddress getEidPrefixAfi();
/**
* Obtains a collection of locator records.
*
* @return a collection of locator records
*/
List<LispLocatorRecord> getLocators();
/**
* Writes LISP message object into communication channel.
*
* @param byteBuf byte buffer
*/
void writeTo(ByteBuf byteBuf);
/**
* A builder of LISP map record.
*/
interface MapRecordBuilder {
......@@ -133,6 +150,14 @@ public interface LispMapRecord {
MapRecordBuilder withEidPrefixAfi(LispAfiAddress prefix);
/**
* Sets a collection of locator records.
*
* @param records a collection of locator records
* @return MapRecordBuilder object
*/
MapRecordBuilder withLocators(List<LispLocatorRecord> records);
/**
* Builds map record.
*
* @return map record instance
......
......@@ -159,12 +159,12 @@ public interface LispMapRegister extends LispMessage {
RegisterBuilder withAuthenticationData(byte[] authenticationData);
/**
* Adds a new record to record list.
* Sets a collection of map records.
*
* @param record record
* @param mapRecords a collection of map records
* @return RegisterBuilder object
*/
RegisterBuilder addRecord(LispMapRecord record);
RegisterBuilder withMapRecords(List<LispMapRecord> mapRecords);
/**
* Builds LISP map register message.
......
......@@ -210,20 +210,20 @@ public interface LispMapRequest extends LispMessage {
RequestBuilder withSourceEid(LispAfiAddress sourceEid);
/**
* Adds ITR RLOC into RLOC collection.
* Sets a collection of ITR RLOCs.
*
* @param itrRloc ITR RLOC
* @param itrRlocs a collection of ITR RLOCs
* @return RequestBuilder object
*/
RequestBuilder addItrRloc(LispAfiAddress itrRloc);
RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs);
/**
* Adds EID record into record collection.
* Sets a collection of EID records.
*
* @param record EID record
* @param records a collection of EID records
* @return RequestBuilder object
*/
RequestBuilder addEidRecord(LispEidRecord record);
RequestBuilder withEidRecords(List<LispEidRecord> records);
/**
* Builds LISP map request message.
......
/*
* 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.protocols;
import com.google.common.testing.EqualsTester;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
/**
* Unit tests for DefaultLispLocatorRecord class.
*/
public final class DefaultLispLocatorRecordTest {
private LispLocatorRecord record1;
private LispLocatorRecord sameAsRecord1;
private LispLocatorRecord record2;
@Before
public void setup() {
LispLocatorRecord.LocatorRecordBuilder builder1 =
new DefaultLispLocatorRecord.DefaultLocatorRecordBuilder();
record1 = builder1
.withPriority((byte) 0x01)
.withWeight((byte) 0x01)
.withMulticastPriority((byte) 0x01)
.withMulticastWeight((byte) 0x01)
.withLocalLocator(true)
.withRlocProbed(false)
.withRouted(true)
.build();
LispLocatorRecord.LocatorRecordBuilder builder2 =
new DefaultLispLocatorRecord.DefaultLocatorRecordBuilder();
sameAsRecord1 = builder2
.withPriority((byte) 0x01)
.withWeight((byte) 0x01)
.withMulticastPriority((byte) 0x01)
.withMulticastWeight((byte) 0x01)
.withLocalLocator(true)
.withRlocProbed(false)
.withRouted(true)
.build();
LispLocatorRecord.LocatorRecordBuilder builder3 =
new DefaultLispLocatorRecord.DefaultLocatorRecordBuilder();
record2 = builder3
.withPriority((byte) 0x02)
.withWeight((byte) 0x02)
.withMulticastPriority((byte) 0x02)
.withMulticastWeight((byte) 0x02)
.withLocalLocator(false)
.withRlocProbed(true)
.withRouted(false)
.build();
}
@Test
public void testEquality() {
new EqualsTester()
.addEqualityGroup(record1, sameAsRecord1)
.addEqualityGroup(record2).testEquals();
}
@Test
public void testConstruction() {
DefaultLispLocatorRecord record = (DefaultLispLocatorRecord) record1;
assertThat(record.getPriority(), is((byte) 0x01));
assertThat(record.getWeight(), is((byte) 0x01));
assertThat(record.getMulticastPriority(), is((byte) 0x01));
assertThat(record.getMulticastWeight(), is((byte) 0x01));
assertThat(record.isLocalLocator(), is(true));
assertThat(record.isRlocProbed(), is(false));
assertThat(record.isRouted(), is(true));
}
}
......@@ -25,7 +25,7 @@ import static org.hamcrest.Matchers.is;
/**
* Unit tests for DefaultLispMapNotify class.
*/
public class DefaultLispMapNotifyTest {
public final class DefaultLispMapNotifyTest {
private LispMapNotify notify1;
private LispMapNotify sameAsNotify1;
......
......@@ -25,7 +25,7 @@ import static org.hamcrest.Matchers.is;
/**
* Unit tests for DefaultLispMapRecord class.
*/
public class DefaultLispMapRecordTest {
public final class DefaultLispMapRecordTest {
private LispMapRecord record1;
private LispMapRecord sameAsRecord1;
......
......@@ -25,7 +25,7 @@ import static org.hamcrest.Matchers.is;
/**
* Unit tests for DefaultLispMapRegister class.
*/
public class DefaultLispMapRegisterTest {
public final class DefaultLispMapRegisterTest {
private LispMapRegister register1;
private LispMapRegister sameAsRegister1;
......
......@@ -25,7 +25,7 @@ import static org.hamcrest.Matchers.is;
/**
* Unit tests for DefaultLispMapReply class.
*/
public class DefaultLispMapReplyTest {
public final class DefaultLispMapReplyTest {
private LispMapReply reply1;
private LispMapReply sameAsReply1;
......
......@@ -25,7 +25,7 @@ import static org.hamcrest.Matchers.is;
/**
* Unit tests for DefaultLispMapRequest class.
*/
public class DefaultLispMapRequestTest {
public final class DefaultLispMapRequestTest {
private LispMapRequest request1;
private LispMapRequest sameAsRequest1;
......
/*
* 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.onlab.util;
/**
* Provide a set of byte operations.
*/
public final class ByteOperator {
/**
* Private constructor which prevents from external instantiation.
*/
private ByteOperator() {
}
/**
* Obtains a specific bit value from a byte with given index number.
*
* @param value byte value
* @param index index number
* @return a specific bit value from a byte
*/
public static boolean getBit(byte value, int index) {
// the length of byte should always be positive whiles less than 8
if (index > 7 || index < 0) {
return false;
}
int bitMask = getHex((int) Math.pow(2, index));
return (value & bitMask) == bitMask;
}
/**
* Converts boolean value into bit.
*
* @param value boolean value
* @param bit bit value
* @return converted bit value
*/
public static byte toBit(boolean value, int bit) {
return (byte) (value ? bit : 0x00);
}
/**
* Convert decimal integer into hex integer.
*
* @param decimal decimal formatted integer
* @return hex formatted integer
*/
private static int getHex(int decimal) {
return Integer.valueOf(String.valueOf(decimal), 16);
}
}
/*
* 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.onlab.util;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
/**
* Unit tests for ByteOperator.
*/
public class ByteOperatorTest {
@Test
public void testGetBit() {
byte eight = 0x08;
assertThat(ByteOperator.getBit(eight, 0), is(false));
assertThat(ByteOperator.getBit(eight, 1), is(false));
assertThat(ByteOperator.getBit(eight, 2), is(false));
assertThat(ByteOperator.getBit(eight, 3), is(true));
assertThat(ByteOperator.getBit(eight, 4), is(false));
assertThat(ByteOperator.getBit(eight, 5), is(false));
assertThat(ByteOperator.getBit(eight, 6), is(false));
assertThat(ByteOperator.getBit(eight, 7), is(false));
byte one = 0x01;
assertThat(ByteOperator.getBit(one, 0), is(true));
assertThat(ByteOperator.getBit(one, 1), is(false));
assertThat(ByteOperator.getBit(one, 2), is(false));
assertThat(ByteOperator.getBit(one, 3), is(false));
assertThat(ByteOperator.getBit(one, 4), is(false));
assertThat(ByteOperator.getBit(one, 5), is(false));
assertThat(ByteOperator.getBit(one, 6), is(false));
assertThat(ByteOperator.getBit(one, 7), is(false));
}
}