[ONOS-4718] Deserialize addresses from LISP control message class

With this commit, we try to deserilize all LispAfiAddress from
all LISP control message classes.

Change-Id: Iaf911bff90c45a70859285e426dc1649c3e6db32
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispLocatorRecord.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispLocatorRecord.java
index 29ad1bd..66ef81d 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispLocatorRecord.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispLocatorRecord.java
@@ -19,6 +19,7 @@
 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.types.LispAfiAddress;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
@@ -222,7 +223,7 @@
         private static final int ROUTED_INDEX = 0;
 
         @Override
-        public LispLocatorRecord readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispLocatorRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             // priority -> 8 bits
             byte priority = (byte) byteBuf.readUnsignedByte();
@@ -250,7 +251,7 @@
             // routed flag -> 1 bit
             boolean routed = ByteOperator.getBit(flags, ROUTED_INDEX);
 
-            // TODO: de-serialize ITR-RLOC AFI and address
+            LispAfiAddress address = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
             return new DefaultLocatorRecordBuilder()
                         .withPriority(priority)
@@ -260,6 +261,7 @@
                         .withLocalLocator(localLocator)
                         .withRlocProbed(rlocProbed)
                         .withRouted(routed)
+                        .withLocatorAfi(address)
                         .build();
         }
     }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapNotify.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapNotify.java
index c80b4d1..05cc7f5 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapNotify.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapNotify.java
@@ -21,6 +21,7 @@
 import io.netty.buffer.ByteBuf;
 import org.onlab.util.ImmutableByteSequence;
 import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
 
 import java.util.List;
 
@@ -183,7 +184,7 @@
         private static final int RESERVED_SKIP_LENGTH = 3;
 
         @Override
-        public LispMapNotify readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispMapNotify readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             if (byteBuf.readerIndex() != 0) {
                 return null;
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 c681e06..b6605d6 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
@@ -21,6 +21,7 @@
 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.types.LispAfiAddress;
 
 import java.util.List;
@@ -225,7 +226,7 @@
         private static final int RESERVED_SKIP_LENGTH = 1;
 
         @Override
-        public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             // Record TTL -> 32 bits
             int recordTtl = byteBuf.readInt();
@@ -249,7 +250,7 @@
             // 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
+            LispAfiAddress eidPrefixAfi = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
             List<LispLocatorRecord> locators = Lists.newArrayList();
             for (int i = 0; i < locatorCount; i++) {
@@ -263,6 +264,7 @@
                         .withAuthoritative(authoritative)
                         .withMapVersionNumber(mapVersionNumber)
                         .withLocators(locators)
+                        .withEidPrefixAfi(eidPrefixAfi)
                         .build();
         }
     }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java
index 058db10..7f75181 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRegister.java
@@ -22,6 +22,7 @@
 import org.onlab.util.ByteOperator;
 import org.onlab.util.ImmutableByteSequence;
 import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
 
 import java.util.List;
 
@@ -110,7 +111,7 @@
     }
 
     @Override
-    public List<LispMapRecord> getLispRecords() {
+    public List<LispMapRecord> getMapRecords() {
         return ImmutableList.copyOf(mapRecords);
     }
 
@@ -224,7 +225,7 @@
         private static final int RESERVED_SKIP_LENGTH = 1;
 
         @Override
-        public LispMapRegister readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispMapRegister readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             if (byteBuf.readerIndex() != 0) {
                 return null;
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReply.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReply.java
index 6e5e218..a180a2d 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReply.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReply.java
@@ -16,9 +16,14 @@
 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.exceptions.LispReaderException;
+
+import java.util.List;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 
@@ -32,6 +37,7 @@
     private final boolean probe;
     private final boolean etr;
     private final boolean security;
+    private final List<LispMapRecord> mapRecords;
 
     /**
      * A private constructor that protects object instantiation from external.
@@ -43,12 +49,13 @@
      * @param security    security flag
      */
     private DefaultLispMapReply(long nonce, byte recordCount, boolean probe,
-                                boolean etr, boolean security) {
+                                boolean etr, boolean security, List<LispMapRecord> mapRecords) {
         this.nonce = nonce;
         this.recordCount = recordCount;
         this.probe = probe;
         this.etr = etr;
         this.security = security;
+        this.mapRecords = mapRecords;
     }
 
     @Override
@@ -92,6 +99,11 @@
     }
 
     @Override
+    public List<LispMapRecord> getMapRecords() {
+        return ImmutableList.copyOf(mapRecords);
+    }
+
+    @Override
     public String toString() {
         return toStringHelper(this)
                 .add("type", getType())
@@ -99,7 +111,8 @@
                 .add("recordCount", recordCount)
                 .add("probe", probe)
                 .add("etr", etr)
-                .add("security", security).toString();
+                .add("security", security)
+                .add("map records", mapRecords).toString();
     }
 
     @Override
@@ -115,12 +128,13 @@
                 Objects.equal(recordCount, that.recordCount) &&
                 Objects.equal(probe, that.probe) &&
                 Objects.equal(etr, that.etr) &&
-                Objects.equal(security, that.security);
+                Objects.equal(security, that.security) &&
+                Objects.equal(mapRecords, that.mapRecords);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(nonce, recordCount, probe, etr, security);
+        return Objects.hashCode(nonce, recordCount, probe, etr, security, mapRecords);
     }
 
     public static final class DefaultReplyBuilder implements ReplyBuilder {
@@ -130,6 +144,7 @@
         private boolean probe;
         private boolean etr;
         private boolean security;
+        private List<LispMapRecord> mapRecords;
 
         @Override
         public LispType getType() {
@@ -167,8 +182,14 @@
         }
 
         @Override
+        public ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
+            this.mapRecords = ImmutableList.copyOf(mapRecords);
+            return this;
+        }
+
+        @Override
         public LispMapReply build() {
-            return new DefaultLispMapReply(nonce, recordCount, probe, etr, security);
+            return new DefaultLispMapReply(nonce, recordCount, probe, etr, security, mapRecords);
         }
     }
 
@@ -183,7 +204,7 @@
         private static final int RESERVED_SKIP_LENGTH = 2;
 
         @Override
-        public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispMapReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             if (byteBuf.readerIndex() != 0) {
                 return null;
@@ -209,7 +230,10 @@
             // nonce -> 64 bits
             long nonce = byteBuf.readLong();
 
-            // TODO: need to de-serialize EID-RLOC records
+            List<LispMapRecord> mapRecords = Lists.newArrayList();
+            for (int i = 0; i < recordCount; i++) {
+                mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
+            }
 
             return new DefaultReplyBuilder()
                         .withIsProbe(probe)
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRequest.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRequest.java
index d2d7bdb..9c6ff92 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRequest.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/DefaultLispMapRequest.java
@@ -21,6 +21,7 @@
 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.types.LispAfiAddress;
 
 import java.util.List;
@@ -296,7 +297,7 @@
         private static final int SMR_INVOKED_INDEX = 6;
 
         @Override
-        public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             if (byteBuf.readerIndex() != 0) {
                 return null;
@@ -335,11 +336,19 @@
             // nonce -> 64 bits
             long nonce = byteBuf.readLong();
 
-            // TODO: de-serialize source EID AFI and address
+            LispAfiAddress sourceEid = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
-            // TODO: de-serialize ITR-RLOC AFI and address
+            // deserialize a collection of RLOC addresses
+            List<LispAfiAddress> itrRlocs = Lists.newArrayList();
+            for (int i = 0; i < irc; i++) {
+                itrRlocs.add(new LispAfiAddress.AfiAddressReader().readFrom(byteBuf));
+            }
 
-            // TODO: de-serialize EID-RECORD
+            // deserialize a collection of EID records
+            List<LispEidRecord> eidRecords = Lists.newArrayList();
+            for (int i = 0; i < recordCount; i++) {
+                eidRecords.add(new LispEidRecord.EidRecordReader().readFrom(byteBuf));
+            }
 
             return new DefaultRequestBuilder()
                         .withIsAuthoritative(authoritative)
@@ -350,6 +359,9 @@
                         .withIsSmrInvoked(smrInvoked)
                         .withNonce(nonce)
                         .withRecordCount((byte) recordCount)
+                        .withSourceEid(sourceEid)
+                        .withEidRecords(eidRecords)
+                        .withItrRlocs(itrRlocs)
                         .build();
         }
     }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java
index 498ce13..1e79d19 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java
@@ -17,6 +17,7 @@
 
 import io.netty.buffer.ByteBuf;
 import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
 import org.onosproject.lisp.msg.types.LispAfiAddress;
 
 /**
@@ -59,20 +60,19 @@
     /**
      * A private LISP message reader for EidRecord portion.
      */
-    private static class EidRecordReader implements LispMessageReader<LispEidRecord> {
+    public static class EidRecordReader implements LispMessageReader<LispEidRecord> {
 
         private static final int RESERVED_SKIP_LENGTH = 1;
 
         @Override
-        public LispEidRecord readFrom(ByteBuf byteBuf) throws LispParseError {
+        public LispEidRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
             // 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;
+            LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
             return new LispEidRecord((byte) maskLength, prefix);
         }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapRegister.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapRegister.java
index 02d2c28..16f6956 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapRegister.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapRegister.java
@@ -103,7 +103,7 @@
      *
      * @return a collection of records
      */
-    List<LispMapRecord> getLispRecords();
+    List<LispMapRecord> getMapRecords();
 
     /**
      * A builder of LISP map register message.
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapReply.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapReply.java
index b28e372..a710fb6 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapReply.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMapReply.java
@@ -15,6 +15,8 @@
  */
 package org.onosproject.lisp.msg.protocols;
 
+import java.util.List;
+
 /**
  * LISP map reply message interface.
  * <p>
@@ -86,6 +88,13 @@
     long getNonce();
 
     /**
+     * Obtains map records.
+     *
+     * @return map records
+     */
+    List<LispMapRecord> getMapRecords();
+
+    /**
      * A builder of LISP map reply message.
      */
     interface ReplyBuilder extends Builder {
@@ -131,6 +140,14 @@
         ReplyBuilder withNonce(long nonce);
 
         /**
+         * Sets a collection of map records.
+         *
+         * @param mapRecords a collection of map records
+         * @return ReplyBuilder object
+         */
+        ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords);
+
+        /**
          * Builds LISP map reply message.
          *
          * @return LISP map reply message
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMessageReader.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMessageReader.java
index b11dc3f..d2b5594 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMessageReader.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispMessageReader.java
@@ -17,6 +17,7 @@
 
 import io.netty.buffer.ByteBuf;
 import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
 
 /**
  * An interface for de-serializing LISP control message.
@@ -30,5 +31,5 @@
      * @return LISP message instance
      * @throws LispParseError LISP control message parse error
      */
-    T readFrom(ByteBuf byteBuf) throws LispParseError;
+    T readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException;
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAfiAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAfiAddress.java
index efc5ea6..006413b 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAfiAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAfiAddress.java
@@ -15,8 +15,14 @@
  */
 package org.onosproject.lisp.msg.types;
 
+import io.netty.buffer.ByteBuf;
+import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
+
 import java.util.Objects;
 
+import static org.onosproject.lisp.msg.types.AddressFamilyIdentifierEnum.*;
+
 /**
  * LISP Locator address typed by Address Family Identifier (AFI).
  */
@@ -67,4 +73,45 @@
         }
         return true;
     }
+
+    public static class AfiAddressReader implements LispAddressReader<LispAfiAddress> {
+
+        @Override
+        public LispAfiAddress readFrom(ByteBuf byteBuf)
+                                    throws LispParseError, LispReaderException {
+
+            int index = byteBuf.readerIndex();
+
+            // AFI code -> 16 bits
+            short afiCode = (short) byteBuf.getUnsignedShort(index);
+
+            // handle IPv4 and IPv6 address
+            if (afiCode == IP.getIanaCode() ||
+                afiCode == IP6.getIanaCode()) {
+                return new LispIpAddress.IpAddressReader().readFrom(byteBuf);
+            }
+
+            // handle distinguished name address
+            if (afiCode == DISTINGUISHED_NAME.getIanaCode()) {
+                return new LispDistinguishedNameAddress.DistinguishedNameAddressReader().readFrom(byteBuf);
+            }
+
+            // handle MAC address
+            if (afiCode == MAC.getIanaCode()) {
+                return new LispMacAddress.MacAddressReader().readFrom(byteBuf);
+            }
+
+            // handle LCAF address
+            if (afiCode == LCAF.getIanaCode()) {
+                return new LispLcafAddress.LcafAddressReader().readFrom(byteBuf);
+            }
+
+            // handle autonomous system address
+            if (afiCode == AS.getIanaCode()) {
+                return new LispAsAddress.AsAddressReader().readFrom(byteBuf);
+            }
+
+            return null;
+        }
+    }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAppDataLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAppDataLcafAddress.java
index 9493911..b1b6fda 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAppDataLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispAppDataLcafAddress.java
@@ -60,6 +60,8 @@
     private LispAfiAddress address;
 
     /**
+     * Initializes application data type LCAF address.
+     *
      * @param protocol       protocol number
      * @param ipTos          IP type of service
      * @param localPortLow   low-ranged local port number
@@ -82,6 +84,35 @@
     }
 
     /**
+     * Initializes application data type LCAF address.
+     *
+     * @param reserved1      reserved1
+     * @param reserved2      reserved2
+     * @param flag           flag
+     * @param length         length
+     * @param protocol       protocol number
+     * @param ipTos          IP type of service
+     * @param localPortLow   low-ranged local port number
+     * @param localPortHigh  high-ranged local port number
+     * @param remotePortLow  low-ranged remote port number
+     * @param remotePortHigh high-ranged remote port number
+     * @param address        address
+     */
+    private LispAppDataLcafAddress(byte reserved1, byte reserved2, byte flag, short length,
+                                   byte protocol, int ipTos, short localPortLow,
+                                   short localPortHigh, short remotePortLow,
+                                   short remotePortHigh, LispAfiAddress address) {
+        super(LispCanonicalAddressFormatEnum.APPLICATION_DATA, reserved1, reserved2, flag, length);
+        this.protocol = protocol;
+        this.ipTos = ipTos;
+        this.localPortLow = localPortLow;
+        this.localPortHigh = localPortHigh;
+        this.remotePortLow = remotePortLow;
+        this.remotePortHigh = remotePortHigh;
+        this.address = address;
+    }
+
+    /**
      * Obtains protocol number.
      *
      * @return protocol number
@@ -182,7 +213,8 @@
                 .toString();
     }
 
-    public static final class AppDataAddressBuilder {
+    public static final class AppDataAddressBuilder
+            extends LcafAddressBuilder<AppDataAddressBuilder> {
         private byte protocol;
         private int ipTos;
         private short localPortLow;
@@ -197,7 +229,7 @@
          * @param protocol protocol number
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withProtocol(byte protocol) {
+        public AppDataAddressBuilder withProtocol(byte protocol) {
             this.protocol = protocol;
             return this;
         }
@@ -208,7 +240,7 @@
          * @param ipTos IP type of service
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withIpTos(int ipTos) {
+        public AppDataAddressBuilder withIpTos(int ipTos) {
             this.ipTos = ipTos;
             return this;
         }
@@ -219,7 +251,7 @@
          * @param localPortLow low-ranged local port number
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withLocalPortLow(short localPortLow) {
+        public AppDataAddressBuilder withLocalPortLow(short localPortLow) {
             this.localPortLow = localPortLow;
             return this;
         }
@@ -230,7 +262,7 @@
          * @param localPortHigh high-ranged local port number
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withLocalPortHigh(short localPortHigh) {
+        public AppDataAddressBuilder withLocalPortHigh(short localPortHigh) {
             this.localPortHigh = localPortHigh;
             return this;
         }
@@ -241,7 +273,7 @@
          * @param remotePortLow low-ranged remote port number
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withRemotePortLow(short remotePortLow) {
+        public AppDataAddressBuilder withRemotePortLow(short remotePortLow) {
             this.remotePortLow = remotePortLow;
             return this;
         }
@@ -252,7 +284,7 @@
          * @param remotePortHigh high-ranged remote port number
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withRemotePortHigh(short remotePortHigh) {
+        public AppDataAddressBuilder withRemotePortHigh(short remotePortHigh) {
             this.remotePortHigh = remotePortHigh;
             return this;
         }
@@ -263,7 +295,7 @@
          * @param address AFI address
          * @return AppDataAddressBuilder object
          */
-        AppDataAddressBuilder withAddress(LispAfiAddress address) {
+        public AppDataAddressBuilder withAddress(LispAfiAddress address) {
             this.address = address;
             return this;
         }
@@ -273,9 +305,10 @@
          *
          * @return LispAddDataLcafAddress instance
          */
-        LispAppDataLcafAddress build() {
-            return new LispAppDataLcafAddress(protocol, ipTos, localPortLow,
-                    localPortHigh, remotePortLow, remotePortHigh, address);
+        public LispAppDataLcafAddress build() {
+            return new LispAppDataLcafAddress(reserved1, reserved2, flag, length,
+                    protocol, ipTos, localPortLow, localPortHigh, remotePortLow,
+                    remotePortHigh, address);
         }
     }
 
@@ -288,6 +321,8 @@
         @Override
         public LispAppDataLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
+            LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
+
             byte[] ipTosByte = new byte[3];
             byteBuf.readBytes(ipTosByte);
 
@@ -298,17 +333,21 @@
             short remotePortLow = (short) byteBuf.readUnsignedShort();
             short remotePortHigh = (short) byteBuf.readUnsignedShort();
 
-            LispAfiAddress address = new LispIpAddress.IpAddressReader().readFrom(byteBuf);
+            LispAfiAddress address = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
             return new AppDataAddressBuilder()
-                        .withProtocol(protocol)
-                        .withIpTos(ipTos)
-                        .withLocalPortLow(localPortLow)
-                        .withLocalPortHigh(localPortHigh)
-                        .withRemotePortLow(remotePortLow)
-                        .withRemotePortHigh(remotePortHigh)
-                        .withAddress(address)
-                        .build();
+                    .withReserved1(lcafAddress.getReserved1())
+                    .withReserved2(lcafAddress.getReserved2())
+                    .withFlag(lcafAddress.getFlag())
+                    .withLength(lcafAddress.getLength())
+                    .withProtocol(protocol)
+                    .withIpTos(ipTos)
+                    .withLocalPortLow(localPortLow)
+                    .withLocalPortHigh(localPortHigh)
+                    .withRemotePortLow(remotePortLow)
+                    .withRemotePortHigh(remotePortHigh)
+                    .withAddress(address)
+                    .build();
         }
 
         /**
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispLcafAddress.java
index 7739929..e6c6c1f 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispLcafAddress.java
@@ -15,9 +15,14 @@
  */
 package org.onosproject.lisp.msg.types;
 
+import io.netty.buffer.ByteBuf;
+import org.onosproject.lisp.msg.exceptions.LispParseError;
+import org.onosproject.lisp.msg.exceptions.LispReaderException;
+
 import java.util.Objects;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onosproject.lisp.msg.types.LispCanonicalAddressFormatEnum.*;
 
 /**
  * LISP Canonical Address Formatted address class.
@@ -35,11 +40,11 @@
  */
 public class LispLcafAddress extends LispAfiAddress {
 
-    protected final LispCanonicalAddressFormatEnum lcafType;
-    protected final byte reserved1;
-    protected final byte reserved2;
-    protected final byte flag;
-    protected final byte length;
+    private final LispCanonicalAddressFormatEnum lcafType;
+    private final byte reserved1;
+    private final byte reserved2;
+    private final byte flag;
+    private final short length;
 
     /**
      * Initializes LCAF address.
@@ -51,7 +56,7 @@
      * @param length length field
      */
     protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
-                              byte reserved1, byte reserved2, byte flag, byte length) {
+                              byte reserved1, byte reserved2, byte flag, short length) {
         super(AddressFamilyIdentifierEnum.LCAF);
         this.lcafType = lcafType;
         this.reserved1 = reserved1;
@@ -69,7 +74,7 @@
      * @param length length field
      */
     protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
-                              byte reserved2, byte flag, byte length) {
+                              byte reserved2, byte flag, short length) {
         super(AddressFamilyIdentifierEnum.LCAF);
         this.lcafType = lcafType;
         this.reserved2 = reserved2;
@@ -86,7 +91,7 @@
      * @param length length field
      */
     protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
-                              byte reserved2, byte length) {
+                              byte reserved2, short length) {
         super(AddressFamilyIdentifierEnum.LCAF);
         this.lcafType = lcafType;
         this.reserved2 = reserved2;
@@ -114,6 +119,21 @@
      * Initializes LCAF address.
      *
      * @param lcafType LCAF type
+     * @param length length field
+     */
+    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, short length) {
+        super(AddressFamilyIdentifierEnum.LCAF);
+        this.lcafType = lcafType;
+        this.reserved1 = 0;
+        this.reserved2 = 0;
+        this.flag = 0;
+        this.length = length;
+    }
+
+    /**
+     * Initializes LCAF address.
+     *
+     * @param lcafType LCAF type
      */
     protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType) {
         super(AddressFamilyIdentifierEnum.LCAF);
@@ -165,10 +185,37 @@
      *
      * @return LCAF length value
      */
-    public byte getLength() {
+    public short getLength() {
         return length;
     }
 
+    /**
+     * Deserializes common fields from byte buffer.
+     *
+     * @param byteBuf byte buffer
+     * @return LispLcafAddress with filled common data fields
+     */
+    public static LispLcafAddress deserializeCommon(ByteBuf byteBuf) {
+
+        // reserved1 -> 8 bits
+        byte reserved1 = (byte) byteBuf.readUnsignedByte();
+
+        // flags -> 8 bits
+        byte flag = (byte) byteBuf.readUnsignedByte();
+
+        // LCAF type -> 8 bits
+        byte lcafType = (byte) byteBuf.readUnsignedByte();
+
+        // reserved2 -> 8bits
+        byte reserved2 = (byte) byteBuf.readUnsignedByte();
+
+        // length -> 16 bits
+        short length = (short) byteBuf.readUnsignedShort();
+
+        return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
+                                    reserved1, reserved2, flag, length);
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(lcafType, reserved1, reserved2, flag, length);
@@ -201,4 +248,110 @@
                 .add("length", length)
                 .toString();
     }
+
+    protected static class LcafAddressBuilder<T> {
+
+        protected byte reserved1;
+        protected byte flag;
+        protected byte lcafType;
+        protected byte reserved2;
+        protected short length;
+
+        /**
+         * Sets reserved1 value.
+         *
+         * @param reserved1 reserved1 value
+         * @return LcafAddressBuilder object
+         */
+        public T withReserved1(byte reserved1) {
+            this.reserved1 = reserved1;
+            return (T) this;
+        }
+
+        /**
+         * Sets flag.
+         *
+         * @param flag flag boolean
+         * @return LcafAddressBuilder object
+         */
+        public T withFlag(byte flag) {
+            this.flag = flag;
+            return (T) this;
+        }
+
+        /**
+         * Sets LCAF type.
+         *
+         * @param lcafType LCAF type
+         * @return LcafAddressBuilder object
+         */
+        public T withLcafType(byte lcafType) {
+            this.lcafType = lcafType;
+            return (T) this;
+        }
+
+        /**
+         * Sets reserved2 value.
+         *
+         * @param reserved2 reserved2 value
+         * @return LcafAddressBuilder object
+         */
+        public T withReserved2(byte reserved2) {
+            this.reserved2 = reserved2;
+            return (T) this;
+        }
+
+        /**
+         * Sets length value.
+         *
+         * @param length length value
+         * @return LcafAddressBuilder object
+         */
+        public T withLength(short length) {
+            this.length = length;
+            return (T) this;
+        }
+
+        /**
+         * Builds LispLcafAddress object.
+         *
+         * @return LispLcafAddress instance
+         */
+        public LispLcafAddress build() {
+            return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
+                                        reserved1, reserved2, flag, length);
+        }
+    }
+
+    public static class LcafAddressReader implements LispAddressReader<LispLcafAddress> {
+
+        private static final int LCAF_TYPE_FIELD_INDEX = 4;
+
+        @Override
+        public LispLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
+
+            int index = byteBuf.readerIndex();
+
+            // LCAF type -> 8 bits
+            byte lcafType = (byte) byteBuf.getUnsignedByte(index + LCAF_TYPE_FIELD_INDEX);
+
+            if (lcafType == APPLICATION_DATA.getLispCode()) {
+                return new LispAppDataLcafAddress.AppDataLcafAddressReader().readFrom(byteBuf);
+            }
+
+            if (lcafType == LIST.getLispCode()) {
+                return new LispListLcafAddress.ListLcafAddressReader().readFrom(byteBuf);
+            }
+
+            if (lcafType == SEGMENT.getLispCode()) {
+                return new LispSegmentLcafAddress.SegmentLcafAddressReader().readFrom(byteBuf);
+            }
+
+            if (lcafType == SOURCE_DEST.getLispCode()) {
+                return new LispSourceDestLcafAddress.SourceDestLcafAddressReader().readFrom(byteBuf);
+            }
+
+            return null;
+        }
+    }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispListLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispListLcafAddress.java
index 2077059..fd33119 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispListLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispListLcafAddress.java
@@ -56,7 +56,7 @@
  */
 public final class LispListLcafAddress extends LispLcafAddress {
 
-    private static final byte LENGTH = 24;
+    private static final short LENGTH = 24;
     List<LispAfiAddress> addresses;
 
     /**
@@ -70,6 +70,20 @@
     }
 
     /**
+     * Initializes list type LCAF address.
+     *
+     * @param reserved1 reserved1 field
+     * @param flag flag
+     * @param reserved2 reserved2 field
+     * @param addresses a set of IPv4 and IPv6 addresses
+     */
+    public LispListLcafAddress(byte reserved1, byte reserved2, byte flag,
+                               List<LispAfiAddress> addresses) {
+        super(LispCanonicalAddressFormatEnum.LIST, reserved1, flag, reserved2, LENGTH);
+        this.addresses = addresses;
+    }
+
+    /**
      * Obtains a set of AFI addresses including IPv4 and IPv6.
      *
      * @return a set of AFI addresses
@@ -111,11 +125,13 @@
         @Override
         public LispListLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
+            LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
 
-            LispAfiAddress ipv4 = new LispIpAddress.IpAddressReader().readFrom(byteBuf);
-            LispAfiAddress ipv6 = new LispIpAddress.IpAddressReader().readFrom(byteBuf);
+            LispAfiAddress ipv4 = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
+            LispAfiAddress ipv6 = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
-            return new LispListLcafAddress(ImmutableList.of(ipv4, ipv6));
+            return new LispListLcafAddress(lcafAddress.getReserved1(), lcafAddress.getReserved2(),
+                                           lcafAddress.getFlag(), ImmutableList.of(ipv4, ipv6));
         }
     }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSegmentLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSegmentLcafAddress.java
index 39ed103..6f2cc22 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSegmentLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSegmentLcafAddress.java
@@ -53,8 +53,8 @@
      * Initializes segment type LCAF address.
      *
      * @param idMaskLength Id mask length
-     * @param instanceId instance id
-     * @param address address
+     * @param instanceId   instance id
+     * @param address      address
      */
     private LispSegmentLcafAddress(byte idMaskLength, int instanceId, LispAfiAddress address) {
         super(LispCanonicalAddressFormatEnum.SEGMENT, idMaskLength);
@@ -63,6 +63,23 @@
     }
 
     /**
+     * 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
@@ -86,12 +103,12 @@
      * @return id mask length
      */
     public byte getIdMaskLength() {
-        return reserved2;
+        return getReserved2();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(address, instanceId, reserved2);
+        return Objects.hash(address, instanceId, getReserved2());
     }
 
     @Override
@@ -103,8 +120,8 @@
         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.reserved2, other.reserved2);
+                    Objects.equals(this.instanceId, other.instanceId) &&
+                    Objects.equals(this.getReserved2(), other.getReserved2());
         }
         return false;
     }
@@ -114,11 +131,12 @@
         return toStringHelper(this)
                 .add("address", address)
                 .add("instanceId", instanceId)
-                .add("idMaskLength", reserved2)
+                .add("idMaskLength", getReserved2())
                 .toString();
     }
 
-    public static final class SegmentAddressBuilder {
+    public static final class SegmentAddressBuilder
+                              extends LcafAddressBuilder<SegmentAddressBuilder> {
         private byte idMaskLength;
         private LispAfiAddress address;
         private int instanceId;
@@ -162,7 +180,8 @@
          * @return LispSegmentLcafAddress instance
          */
         public LispSegmentLcafAddress build() {
-            return new LispSegmentLcafAddress(idMaskLength, instanceId, address);
+            return new LispSegmentLcafAddress(reserved1, idMaskLength, flag,
+                                              length, instanceId, address);
         }
     }
 
@@ -170,22 +189,27 @@
      * Segment LCAF address reader class.
      */
     public static class SegmentLcafAddressReader
-                        implements LispAddressReader<LispSegmentLcafAddress> {
+            implements LispAddressReader<LispSegmentLcafAddress> {
 
         @Override
         public LispSegmentLcafAddress readFrom(ByteBuf byteBuf)
-                                        throws LispParseError, LispReaderException {
+                throws LispParseError, LispReaderException {
 
-            // TODO: need to de-serialize IdMaskLength
-            byte idMaskLength = 0x01;
+            LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
+
+            byte idMaskLength = lcafAddress.getReserved2();
+
             int instanceId = (int) byteBuf.readUnsignedInt();
-            LispAfiAddress address = new LispIpAddress.IpAddressReader().readFrom(byteBuf);
+            LispAfiAddress address = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
             return new SegmentAddressBuilder()
-                            .withIdMaskLength(idMaskLength)
-                            .withInstanceId(instanceId)
-                            .withAddress(address)
-                            .build();
+                    .withReserved1(lcafAddress.getReserved1())
+                    .withFlag(lcafAddress.getFlag())
+                    .withLength(lcafAddress.getLength())
+                    .withIdMaskLength(idMaskLength)
+                    .withInstanceId(instanceId)
+                    .withAddress(address)
+                    .build();
         }
     }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSourceDestLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSourceDestLcafAddress.java
index 24d159a..9da4a18 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSourceDestLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispSourceDestLcafAddress.java
@@ -76,6 +76,31 @@
     }
 
     /**
+     * Initializes source/dest key type LCAF address.
+     *
+     * @param reserved1     reserved1
+     * @param reserved2     reserved2
+     * @param flag          flag
+     * @param length        length
+     * @param reserved      reserved
+     * @param srcMaskLength source mask length
+     * @param dstMaskLength destination mask length
+     * @param srcPrefix     source address prefix
+     * @param dstPrefix     destination address prefix
+     */
+    private LispSourceDestLcafAddress(byte reserved1, byte reserved2, byte flag, short length,
+                                      short reserved, byte srcMaskLength,
+                                      byte dstMaskLength, LispAfiAddress srcPrefix,
+                                      LispAfiAddress dstPrefix) {
+        super(LispCanonicalAddressFormatEnum.SOURCE_DEST, reserved1, reserved2, flag, length);
+        this.reserved = reserved;
+        this.srcMaskLength = srcMaskLength;
+        this.dstMaskLength = dstMaskLength;
+        this.srcPrefix = srcPrefix;
+        this.dstPrefix = dstPrefix;
+    }
+
+    /**
      * Obtains source address prefix.
      *
      * @return source address prefix
@@ -153,7 +178,8 @@
                 .toString();
     }
 
-    public static final class SourceDestAddressBuilder {
+    public static final class SourceDestAddressBuilder
+            extends LcafAddressBuilder<SourceDestAddressBuilder> {
         private LispAfiAddress srcPrefix;
         private LispAfiAddress dstPrefix;
         private byte srcMaskLength;
@@ -221,8 +247,8 @@
          * @return LispSourceDestLcafAddress instance
          */
         public LispSourceDestLcafAddress build() {
-            return new LispSourceDestLcafAddress(reserved, srcMaskLength,
-                    dstMaskLength, srcPrefix, dstPrefix);
+            return new LispSourceDestLcafAddress(reserved1, reserved2, flag, length,
+                    reserved, srcMaskLength, dstMaskLength, srcPrefix, dstPrefix);
         }
     }
 
@@ -235,20 +261,26 @@
         @Override
         public LispSourceDestLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
+            LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
+
             short reserved = byteBuf.readShort();
             byte srcMaskLength = (byte) byteBuf.readUnsignedByte();
             byte dstMaskLength = (byte) byteBuf.readUnsignedByte();
 
-            LispAfiAddress srcPrefix = new LispIpAddress.IpAddressReader().readFrom(byteBuf);
-            LispAfiAddress dstPrefix = new LispIpAddress.IpAddressReader().readFrom(byteBuf);
+            LispAfiAddress srcPrefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
+            LispAfiAddress dstPrefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
 
             return new SourceDestAddressBuilder()
-                            .withReserved(reserved)
-                            .withSrcMaskLength(srcMaskLength)
-                            .withDstMaskLength(dstMaskLength)
-                            .withSrcPrefix(srcPrefix)
-                            .withDstPrefix(dstPrefix)
-                            .build();
+                    .withReserved1(lcafAddress.getReserved1())
+                    .withReserved2(lcafAddress.getReserved2())
+                    .withFlag(lcafAddress.getFlag())
+                    .withLength(lcafAddress.getLength())
+                    .withReserved(reserved)
+                    .withSrcMaskLength(srcMaskLength)
+                    .withDstMaskLength(dstMaskLength)
+                    .withSrcPrefix(srcPrefix)
+                    .withDstPrefix(dstPrefix)
+                    .build();
         }
     }
 }
diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispLcafAddressTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispLcafAddressTest.java
index 99077d1..e0b61b2 100644
--- a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispLcafAddressTest.java
+++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispLcafAddressTest.java
@@ -57,6 +57,6 @@
         assertThat(lcafAddress.getReserved1(), is((byte) 0x01));
         assertThat(lcafAddress.getReserved2(), is((byte) 0x01));
         assertThat(lcafAddress.getFlag(), is((byte) 0x01));
-        assertThat(lcafAddress.getLength(), is((byte) 0x01));
+        assertThat(lcafAddress.getLength(), is((short) 1));
     }
 }