[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
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRecord.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRecord.java
index 7b0c86c..c681e06 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRecord.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRecord.java
@@ -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 @@
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 @@
*/
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 @@
this.authoritative = authoritative;
this.mapVersionNumber = mapVersionNumber;
this.eidPrefixAfi = eidPrefixAfi;
+ this.locatorRecords = locatorRecords;
}
@Override
@@ -94,6 +102,16 @@
}
@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 @@
.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 @@
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 @@
private boolean authoritative;
private short mapVersionNumber;
private LispAfiAddress eidPrefixAfi;
+ private List<LispLocatorRecord> locatorRecords;
@Override
public MapRecordBuilder withRecordTtl(int recordTtl) {
@@ -182,20 +204,66 @@
}
@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();
}
}
}