Bugfix: Parse the LCAF address by referring to length field value

Change-Id: Ia43521f531ad03f609219048f0fb1485118cd181
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 ccb30c3..fe91471 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
@@ -381,6 +381,7 @@
         public void writeTo(ByteBuf byteBuf, LispAppDataLcafAddress address)
                 throws LispWriterException {
 
+            int lcafIndex = byteBuf.writerIndex();
             LispLcafAddress.serializeCommon(byteBuf, address);
 
             byte[] tos = getPartialByteArray(address.getIpTos());
@@ -393,6 +394,8 @@
 
             AfiAddressWriter writer = new LispAfiAddress.AfiAddressWriter();
             writer.writeTo(byteBuf, address.getAddress());
+
+            LispLcafAddress.updateLength(lcafIndex, byteBuf);
         }
 
         /**
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 073ca5a..97e4752 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
@@ -53,6 +53,9 @@
 
     private static final int LCAF_AFI_CODE_BYTE_LENGTH = 2;
 
+    private static final int LENGTH_FIELD_INDEX = 7;
+    public static final int COMMON_HEADER_SIZE = 8;
+
     /**
      * Initializes LCAF address.
      *
@@ -228,12 +231,26 @@
     }
 
     /**
+     * Updates the header length field value based on the size of LISP header.
+     *
+     * @param lcafIndex the index of LCAF address, because LCAF address is
+     *                  contained inside LISP control message, so to correctly
+     *                  find the right LCAF length index, we need to know the
+     *                  absolute lcaf index inside LISP control message byte buf
+     * @param byteBuf   netty byte buffer
+     */
+    public static void updateLength(int lcafIndex, ByteBuf byteBuf) {
+        byteBuf.setByte(lcafIndex + LENGTH_FIELD_INDEX, byteBuf.writerIndex() - COMMON_HEADER_SIZE);
+    }
+
+    /**
      * Serializes common fields to byte buffer.
      *
      * @param byteBuf byte buffer
      * @param address LISP LCAF address instance
      */
     public static void serializeCommon(ByteBuf byteBuf, LispLcafAddress address) {
+
         byteBuf.writeShort(AddressFamilyIdentifierEnum.LCAF.getIanaCode());
         byteBuf.writeByte(address.getReserved1());
         byteBuf.writeByte(address.getFlag());
@@ -381,7 +398,7 @@
             }
 
             if (lcafType == TRAFFIC_ENGINEERING.getLispCode()) {
-                return new LispTeLcafAddress.TeAddressBuilder.TeLcafAddressReader().readFrom(byteBuf);
+                return new LispTeLcafAddress.TeLcafAddressReader().readFrom(byteBuf);
             }
 
             log.warn("Unsupported LCAF type, please specify a correct LCAF type");
@@ -415,7 +432,7 @@
                             (LispSourceDestLcafAddress) address);
                     break;
                 case TRAFFIC_ENGINEERING:
-                    new LispTeLcafAddress.TeAddressBuilder.TeLcafAddressWriter().writeTo(byteBuf,
+                    new LispTeLcafAddress.TeLcafAddressWriter().writeTo(byteBuf,
                             (LispTeLcafAddress) address);
                     break;
                 default:
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 170737c..eb86b65 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
@@ -186,6 +186,7 @@
         @Override
         public void writeTo(ByteBuf byteBuf, LispListLcafAddress address) throws LispWriterException {
 
+            int lcafIndex = byteBuf.writerIndex();
             LispLcafAddress.serializeCommon(byteBuf, address);
 
             LispIpv4Address.Ipv4AddressWriter v4Writer = new LispIpv4Address.Ipv4AddressWriter();
@@ -201,6 +202,8 @@
             // IPv6 address
             byteBuf.writeShort(ipv6.getAfi().getIanaCode());
             v6Writer.writeTo(byteBuf, (LispIpv6Address) ipv6);
+
+            LispLcafAddress.updateLength(lcafIndex, byteBuf);
         }
     }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispNatLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispNatLcafAddress.java
index f9f4f2a..70f046a 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispNatLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispNatLcafAddress.java
@@ -280,13 +280,14 @@
             short msUdpPortNumber = (short) byteBuf.readUnsignedShort();
             short etrUdpPortNumber = (short) byteBuf.readUnsignedShort();
 
-            LispAfiAddress globalEtrRlocAddress = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
-            LispAfiAddress msRlocAddress = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
-            LispAfiAddress privateEtrRlocAddress = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
+            LispAfiAddress globalEtrRlocAddress = new AfiAddressReader().readFrom(byteBuf);
+            LispAfiAddress msRlocAddress = new AfiAddressReader().readFrom(byteBuf);
+            LispAfiAddress privateEtrRlocAddress = new AfiAddressReader().readFrom(byteBuf);
 
             List<LispAfiAddress> rtrRlocAddresses = Lists.newArrayList();
-            for (int i = 0; i < lcafAddress.getLength(); i++) {
-                rtrRlocAddresses.add(new LispAfiAddress.AfiAddressReader().readFrom(byteBuf));
+
+            while (byteBuf.readerIndex() - LispLcafAddress.COMMON_HEADER_SIZE < lcafAddress.getLength()) {
+                rtrRlocAddresses.add(new AfiAddressReader().readFrom(byteBuf));
             }
 
             return new NatAddressBuilder()
@@ -313,6 +314,7 @@
         public void writeTo(ByteBuf byteBuf, LispNatLcafAddress address)
                 throws LispWriterException {
 
+            int lcafIndex = byteBuf.writerIndex();
             LispLcafAddress.serializeCommon(byteBuf, address);
 
             byteBuf.writeShort(address.getMsUdpPortNumber());
@@ -328,6 +330,8 @@
             for (int i = 0; i < rtrRlocAddresses.size(); i++) {
                 writer.writeTo(byteBuf, rtrRlocAddresses.get(i));
             }
+
+            LispLcafAddress.updateLength(lcafIndex, byteBuf);
         }
     }
 }
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 50e4128..f6a715a 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
@@ -228,11 +228,14 @@
         public void writeTo(ByteBuf byteBuf, LispSegmentLcafAddress address)
                 throws LispWriterException {
 
+            int lcafIndex = byteBuf.writerIndex();
             LispLcafAddress.serializeCommon(byteBuf, address);
 
             byteBuf.writeInt(address.getInstanceId());
 
             new LispAfiAddress.AfiAddressWriter().writeTo(byteBuf, address.getAddress());
+
+            LispLcafAddress.updateLength(lcafIndex, byteBuf);
         }
     }
 }
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 08d9205..dd21127 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
@@ -300,6 +300,7 @@
         public void writeTo(ByteBuf byteBuf, LispSourceDestLcafAddress address)
                 throws LispWriterException {
 
+            int lcafIndex = byteBuf.writerIndex();
             LispLcafAddress.serializeCommon(byteBuf, address);
 
             byteBuf.writeShort(address.getReserved());
@@ -308,6 +309,8 @@
             AfiAddressWriter writer = new LispAfiAddress.AfiAddressWriter();
             writer.writeTo(byteBuf, address.getSrcPrefix());
             writer.writeTo(byteBuf, address.getDstPrefix());
+
+            LispLcafAddress.updateLength(lcafIndex, byteBuf);
         }
     }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispTeLcafAddress.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispTeLcafAddress.java
index 6133ea0..6a64c64 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispTeLcafAddress.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/types/LispTeLcafAddress.java
@@ -62,8 +62,8 @@
      *
      * @param records a collection of Re-encapsulated RLOC addresses
      */
-    private LispTeLcafAddress(short length, List<LispTeRecord> records) {
-        super(LispCanonicalAddressFormatEnum.TRAFFIC_ENGINEERING, length);
+    private LispTeLcafAddress(List<LispTeRecord> records) {
+        super(LispCanonicalAddressFormatEnum.TRAFFIC_ENGINEERING);
         this.records = records;
     }
 
@@ -102,8 +102,6 @@
 
     public static final class TeAddressBuilder extends LcafAddressBuilder<TeAddressBuilder> {
         private List<LispTeRecord> records;
-        private short length;
-        private static final int SIZE_OF_AFI_RECORD = 8;
 
         /**
          * Sets a collection of TE records.
@@ -113,7 +111,6 @@
          */
         public TeAddressBuilder withTeRecords(List<LispTeRecord> records) {
             this.records = records;
-            this.length = (short) (records.size() * SIZE_OF_AFI_RECORD);
             return this;
         }
 
@@ -123,51 +120,49 @@
          * @return LispTeLcafAddress instance
          */
         public LispTeLcafAddress build() {
-            return new LispTeLcafAddress(length, records);
+            return new LispTeLcafAddress(records);
         }
+    }
+    /**
+     * TE LCAF address reader class.
+     */
+    public static class TeLcafAddressReader implements LispAddressReader<LispTeLcafAddress> {
 
-        /**
-         * TE LCAF address reader class.
-         */
-        public static class TeLcafAddressReader implements LispAddressReader<LispTeLcafAddress> {
+        @Override
+        public LispTeLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
 
-            private static final int SIZE_OF_AFI_RECORD = 8;
+            LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
 
-            @Override
-            public LispTeLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
-
-                LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
-
-                // TODO: for RTR RLOC is IPv4 only for now
-                int numOfRecords = lcafAddress.getLength() / SIZE_OF_AFI_RECORD;
-
-                List<LispTeRecord> teRecords = Lists.newArrayList();
-                for (int i = 0; i < numOfRecords; i++) {
-                    teRecords.add(new LispTeRecord.TeRecordReader().readFrom(byteBuf));
-                }
-
-                return new TeAddressBuilder()
-                            .withTeRecords(teRecords)
-                            .build();
+            List<LispTeRecord> teRecords = Lists.newArrayList();
+            while (byteBuf.readerIndex() - LispLcafAddress.COMMON_HEADER_SIZE < lcafAddress.getLength()) {
+                teRecords.add(new LispTeRecord.TeRecordReader().readFrom(byteBuf));
             }
+
+            return new TeAddressBuilder()
+                        .withTeRecords(teRecords)
+                        .build();
         }
+    }
 
-        /**
-         * TE LCAF address writer class.
-         */
-        public static class TeLcafAddressWriter implements LispAddressWriter<LispTeLcafAddress> {
+    /**
+     * TE LCAF address writer class.
+     */
+    public static class TeLcafAddressWriter implements LispAddressWriter<LispTeLcafAddress> {
 
-            @Override
-            public void writeTo(ByteBuf byteBuf, LispTeLcafAddress address) throws LispWriterException {
-                LispLcafAddress.serializeCommon(byteBuf, address);
+        @Override
+        public void writeTo(ByteBuf byteBuf, LispTeLcafAddress address) throws LispWriterException {
 
-                TeRecordWriter writer = new TeRecordWriter();
+            int lcafIndex = byteBuf.writerIndex();
+            LispLcafAddress.serializeCommon(byteBuf, address);
 
-                List<LispTeRecord> teRecords = address.getTeRecords();
-                for (int i = 0; i < teRecords.size(); i++) {
-                    writer.writeTo(byteBuf, teRecords.get(i));
-                }
+            TeRecordWriter writer = new TeRecordWriter();
+
+            List<LispTeRecord> teRecords = address.getTeRecords();
+            for (int i = 0; i < teRecords.size(); i++) {
+                writer.writeTo(byteBuf, teRecords.get(i));
             }
+
+            LispLcafAddress.updateLength(lcafIndex, byteBuf);
         }
     }
 }
diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java
index 2ab8002..7e3849a 100644
--- a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java
+++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispInfoReplyTest.java
@@ -30,6 +30,7 @@
 import org.onosproject.lisp.msg.protocols.LispInfoReply.InfoReplyBuilder;
 import org.onosproject.lisp.msg.types.LispIpv4Address;
 import org.onosproject.lisp.msg.types.LispNatLcafAddress;
+import org.onosproject.lisp.msg.types.LispNatLcafAddress.NatAddressBuilder;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -58,14 +59,14 @@
 
         LispIpv4Address address1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.4"));
 
-        LispNatLcafAddress natLcafAddress1 = new LispNatLcafAddress.NatAddressBuilder()
-                                                        .withLength((short) 0)
-                                                        .withMsUdpPortNumber(msUdpPortNumber1)
-                                                        .withEtrUdpPortNumber(etrUdpPortNumber1)
-                                                        .withGlobalEtrRlocAddress(globalEtrRlocAddress1)
-                                                        .withMsRlocAddress(msRlocAddress1)
-                                                        .withPrivateEtrRlocAddress(privateEtrRlocAddress1)
-                                                        .build();
+        LispNatLcafAddress natLcafAddress1 = new NatAddressBuilder()
+                                                    .withLength((short) 0)
+                                                    .withMsUdpPortNumber(msUdpPortNumber1)
+                                                    .withEtrUdpPortNumber(etrUdpPortNumber1)
+                                                    .withGlobalEtrRlocAddress(globalEtrRlocAddress1)
+                                                    .withMsRlocAddress(msRlocAddress1)
+                                                    .withPrivateEtrRlocAddress(privateEtrRlocAddress1)
+                                                    .build();
 
         reply1 = builder1
                     .withNonce(1L)
@@ -97,14 +98,14 @@
 
         LispIpv4Address address2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.4"));
 
-        LispNatLcafAddress natLcafAddress2 = new LispNatLcafAddress.NatAddressBuilder()
-                                                        .withLength((short) 0)
-                                                        .withMsUdpPortNumber(msUdpPortNumber2)
-                                                        .withEtrUdpPortNumber(etrUdpPortNumber2)
-                                                        .withGlobalEtrRlocAddress(globalEtrRlocAddress2)
-                                                        .withMsRlocAddress(msRlocAddress2)
-                                                        .withPrivateEtrRlocAddress(privateEtrRlocAddress2)
-                                                        .build();
+        LispNatLcafAddress natLcafAddress2 = new NatAddressBuilder()
+                                                    .withLength((short) 0)
+                                                    .withMsUdpPortNumber(msUdpPortNumber2)
+                                                    .withEtrUdpPortNumber(etrUdpPortNumber2)
+                                                    .withGlobalEtrRlocAddress(globalEtrRlocAddress2)
+                                                    .withMsRlocAddress(msRlocAddress2)
+                                                    .withPrivateEtrRlocAddress(privateEtrRlocAddress2)
+                                                    .build();
 
         reply2 = builder3
                         .withNonce(2L)
@@ -135,7 +136,7 @@
         LispIpv4Address msRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.2"));
         LispIpv4Address privateEtrRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.3"));
 
-        LispNatLcafAddress natLcafAddress = new LispNatLcafAddress.NatAddressBuilder()
+        LispNatLcafAddress natLcafAddress = new NatAddressBuilder()
                 .withLength((short) 0)
                 .withMsUdpPortNumber(msUdpPortNumber1)
                 .withEtrUdpPortNumber(etrUdpPortNumber1)
diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispNatLcafAddressTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispNatLcafAddressTest.java
index f8584bdc..2fb6b25 100644
--- a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispNatLcafAddressTest.java
+++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispNatLcafAddressTest.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.lisp.msg.types;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.testing.EqualsTester;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
@@ -28,6 +29,8 @@
 import org.onosproject.lisp.msg.types.LispNatLcafAddress.NatLcafAddressReader;
 import org.onosproject.lisp.msg.types.LispNatLcafAddress.NatLcafAddressWriter;
 
+import java.util.List;
+
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
@@ -51,6 +54,10 @@
         LispIpv4Address msRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.2"));
         LispIpv4Address privateEtrRlocAddress1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.3"));
 
+        LispIpv4Address rtrRloc11 = new LispIpv4Address(IpAddress.valueOf("10.1.1.1"));
+        LispIpv4Address rtrRloc12 = new LispIpv4Address(IpAddress.valueOf("10.1.1.2"));
+        List<LispAfiAddress> rtrRlocs1 = ImmutableList.of(rtrRloc11, rtrRloc12);
+
         address1 = builder1
                         .withLength((short) 0)
                         .withMsUdpPortNumber(msUdpPortNumber1)
@@ -58,6 +65,7 @@
                         .withGlobalEtrRlocAddress(globalEtrRlocAddress1)
                         .withMsRlocAddress(msRlocAddress1)
                         .withPrivateEtrRlocAddress(privateEtrRlocAddress1)
+                        .withRtrRlocAddresses(rtrRlocs1)
                         .build();
 
         NatAddressBuilder builder2 = new NatAddressBuilder();
@@ -69,6 +77,7 @@
                         .withGlobalEtrRlocAddress(globalEtrRlocAddress1)
                         .withMsRlocAddress(msRlocAddress1)
                         .withPrivateEtrRlocAddress(privateEtrRlocAddress1)
+                        .withRtrRlocAddresses(rtrRlocs1)
                         .build();
 
         NatAddressBuilder builder3 = new NatAddressBuilder();
@@ -79,6 +88,10 @@
         LispIpv4Address msRlocAddress2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.2"));
         LispIpv4Address privateEtrRlocAddress2 = new LispIpv4Address(IpAddress.valueOf("192.168.2.3"));
 
+        LispIpv4Address rtrRloc21 = new LispIpv4Address(IpAddress.valueOf("10.1.2.1"));
+        LispIpv4Address rtrRloc22 = new LispIpv4Address(IpAddress.valueOf("10.1.2.2"));
+        List<LispAfiAddress> rtrRlocs2 = ImmutableList.of(rtrRloc21, rtrRloc22);
+
         address2 = builder3
                         .withLength((short) 0)
                         .withMsUdpPortNumber(msUdpPortNumber2)
@@ -86,6 +99,7 @@
                         .withGlobalEtrRlocAddress(globalEtrRlocAddress2)
                         .withMsRlocAddress(msRlocAddress2)
                         .withPrivateEtrRlocAddress(privateEtrRlocAddress2)
+                        .withRtrRlocAddresses(rtrRlocs2)
                         .build();
     }
 
diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispTeLcafAddressTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispTeLcafAddressTest.java
index 1b58f60..b800e6e 100644
--- a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispTeLcafAddressTest.java
+++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/types/LispTeLcafAddressTest.java
@@ -26,8 +26,8 @@
 import org.onosproject.lisp.msg.exceptions.LispReaderException;
 import org.onosproject.lisp.msg.exceptions.LispWriterException;
 import org.onosproject.lisp.msg.types.LispTeLcafAddress.TeAddressBuilder;
-import org.onosproject.lisp.msg.types.LispTeLcafAddress.TeAddressBuilder.TeLcafAddressReader;
-import org.onosproject.lisp.msg.types.LispTeLcafAddress.TeAddressBuilder.TeLcafAddressWriter;
+import org.onosproject.lisp.msg.types.LispTeLcafAddress.TeLcafAddressReader;
+import org.onosproject.lisp.msg.types.LispTeLcafAddress.TeLcafAddressWriter;
 import org.onosproject.lisp.msg.types.LispTeRecord.TeRecordBuilder;
 
 import static org.hamcrest.MatcherAssert.assertThat;