[ONOS-3856] BGP flow specification update message encode.

Change-Id: I4286ea636df154f64c5b27f1f55a26fdc257e4f3
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java
index 23dd7d5..9fda0a6 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpUpdateMsg.java
@@ -21,7 +21,6 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.onlab.packet.IpPrefix;
 import org.onosproject.bgpio.protocol.ver4.BgpPathAttributes;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
 import org.onosproject.bgpio.types.BgpValueType;
 import org.onosproject.bgpio.types.BgpHeader;
 
@@ -51,10 +50,6 @@
 
         Builder setBgpPathAttributes(List<BgpValueType> attributes);
 
-        Builder setNlriIdentifier(short afi, byte safi);
-
-        Builder setBgpFlowSpecComponents(BgpFlowSpecDetails flowSpecComponents);
-
         @Override
         Builder setHeader(BgpHeader bgpMsgHeader);
     }
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetails.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetails.java
index 2f2eb6f..cc6384c 100755
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetails.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetails.java
@@ -27,8 +27,8 @@
  */
 public class BgpFlowSpecDetails {
     private List<BgpValueType> flowSpecComponents;
-    BgpValueType fsActionTlv;
-    RouteDistinguisher routeDistinguisher;
+    private BgpValueType fsActionTlv;
+    private RouteDistinguisher routeDistinguisher;
 
     /**
      * Flow specification details object constructor with the parameter.
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
index 7189ef6..8bead96 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
@@ -17,12 +17,14 @@
 
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.types.As4Path;
 import org.onosproject.bgpio.types.AsPath;
 import org.onosproject.bgpio.types.BgpErrorType;
+import org.onosproject.bgpio.types.BgpExtendedCommunity;
 import org.onosproject.bgpio.types.BgpValueType;
 import org.onosproject.bgpio.types.LinkStateAttributes;
 import org.onosproject.bgpio.types.LocalPref;
@@ -33,6 +35,7 @@
 import org.onosproject.bgpio.types.MpUnReachNlri;
 import org.onosproject.bgpio.util.UnSupportedAttribute;
 import org.onosproject.bgpio.util.Validation;
+import org.onosproject.bgpio.util.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -58,6 +61,7 @@
     public static final int LINK_STATE_ATTRIBUTE_TYPE = 29;
     public static final int MPREACHNLRI_TYPE = 14;
     public static final int MPUNREACHNLRI_TYPE = 15;
+    public static final int EXTENDED_COMMUNITY_TYPE = 16;
 
     private final List<BgpValueType> pathAttribute;
 
@@ -142,6 +146,9 @@
             case LINK_STATE_ATTRIBUTE_TYPE:
                 pathAttribute = LinkStateAttributes.read(cb);
                 break;
+            case EXTENDED_COMMUNITY_TYPE:
+                pathAttribute = BgpExtendedCommunity.read(cb);
+                break;
             default:
                 //skip bytes for unsupported attribute types
                 UnSupportedAttribute.read(cb);
@@ -155,6 +162,81 @@
     }
 
     /**
+     * Write path attributes to channelBuffer.
+     *
+     * @param cb channelBuffer
+     * @return object of BgpPathAttributes
+     * @throws BgpParseException while parsing BGP path attributes
+     */
+    public int write(ChannelBuffer cb)
+            throws BgpParseException {
+
+        if (pathAttribute == null) {
+            return 0;
+        }
+        int iLenStartIndex = cb.writerIndex();
+
+        ListIterator<BgpValueType> iterator = pathAttribute.listIterator();
+
+        int pathAttributeIndx = cb.writerIndex();
+        cb.writeShort(0);
+
+        while (iterator.hasNext()) {
+
+            BgpValueType attr = iterator.next();
+
+            switch (attr.getType()) {
+            case Origin.ORIGIN_TYPE:
+                Origin origin = (Origin) attr;
+                origin.write(cb);
+                break;
+            case AsPath.ASPATH_TYPE:
+                AsPath asPath = (AsPath) attr;
+                asPath.write(cb);
+                break;
+            case As4Path.AS4PATH_TYPE:
+                As4Path as4Path = (As4Path) attr;
+                as4Path.write(cb);
+                break;
+            case NextHop.NEXTHOP_TYPE:
+                NextHop nextHop = (NextHop) attr;
+                nextHop.write(cb);
+                break;
+            case Med.MED_TYPE:
+                Med med = (Med) attr;
+                med.write(cb);
+                break;
+            case LocalPref.LOCAL_PREF_TYPE:
+                LocalPref localPref = (LocalPref) attr;
+                localPref.write(cb);
+                break;
+            case Constants.BGP_EXTENDED_COMMUNITY:
+                BgpExtendedCommunity extendedCommunity = (BgpExtendedCommunity) attr;
+                extendedCommunity.write(cb);
+                break;
+            case MpReachNlri.MPREACHNLRI_TYPE:
+                MpReachNlri mpReach = (MpReachNlri) attr;
+                mpReach.write(cb);
+                break;
+            case MpUnReachNlri.MPUNREACHNLRI_TYPE:
+                MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
+                mpUnReach.write(cb);
+                break;
+            case LINK_STATE_ATTRIBUTE_TYPE:
+                LinkStateAttributes linkState = (LinkStateAttributes) attr;
+                linkState.write(cb);
+                break;
+            default:
+                return cb.writerIndex() - iLenStartIndex;
+            }
+        }
+
+        int pathAttrLen = cb.writerIndex() - pathAttributeIndx;
+        cb.setShort(pathAttributeIndx, (short) (pathAttrLen - 2));
+        return cb.writerIndex() - iLenStartIndex;
+    }
+
+    /**
      * Checks mandatory attributes are presents, if not present throws exception.
      *
      * @param isOrigin say whether origin attribute is present
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java
index 7b3264e..e2bf218 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.bgpio.protocol.ver4;
 
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -26,9 +27,10 @@
 import org.onosproject.bgpio.protocol.BgpType;
 import org.onosproject.bgpio.protocol.BgpUpdateMsg;
 import org.onosproject.bgpio.protocol.BgpVersion;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
 import org.onosproject.bgpio.types.BgpErrorType;
 import org.onosproject.bgpio.types.BgpHeader;
+import org.onosproject.bgpio.types.MpReachNlri;
+import org.onosproject.bgpio.types.MpUnReachNlri;
 import org.onosproject.bgpio.util.Constants;
 import org.onosproject.bgpio.util.Validation;
 
@@ -94,9 +96,6 @@
     private BgpPathAttributes bgpPathAttributes;
     private BgpHeader bgpHeader;
     private List<IpPrefix> nlri;
-    private BgpFlowSpecDetails bgpFlowSpecComponents;
-    private short afi;
-    private byte safi;
 
     /**
      * Constructor to initialize parameters for BGP Update message.
@@ -114,15 +113,6 @@
         this.nlri = nlri;
     }
 
-    public BgpUpdateMsgVer4(BgpHeader bgpHeader, short afi, byte safi, BgpPathAttributes bgpPathAttributes,
-                                    BgpFlowSpecDetails bgpFlowSpecComponents) {
-        this.bgpHeader = bgpHeader;
-        this.bgpFlowSpecComponents = bgpFlowSpecComponents;
-        this.bgpPathAttributes = bgpPathAttributes;
-        this.afi = afi;
-        this.safi = safi;
-    }
-
     /**
      * Reader reads BGP Update Message from the channel buffer.
      */
@@ -191,16 +181,15 @@
      */
     static class Builder implements BgpUpdateMsg.Builder {
         BgpHeader bgpMsgHeader = null;
-        BgpFlowSpecDetails bgpFlowSpecComponents;
         BgpPathAttributes bgpPathAttributes;
-        private short afi;
-        private byte safi;
+        List<IpPrefix> withdrawnRoutes;
+        List<IpPrefix> nlri;
 
         @Override
-        public BgpUpdateMsg build() /* throws BgpParseException */ {
+        public BgpUpdateMsg build() {
             BgpHeader bgpMsgHeader = DEFAULT_UPDATE_HEADER;
 
-            return new BgpUpdateMsgVer4(bgpMsgHeader, afi, safi, bgpPathAttributes, bgpFlowSpecComponents);
+            return new BgpUpdateMsgVer4(bgpMsgHeader, withdrawnRoutes, bgpPathAttributes, nlri);
         }
 
         @Override
@@ -210,23 +199,11 @@
         }
 
         @Override
-        public Builder setBgpFlowSpecComponents(BgpFlowSpecDetails bgpFlowSpecComponents) {
-            this.bgpFlowSpecComponents = bgpFlowSpecComponents;
-            return this;
-        }
-
-        @Override
         public Builder setBgpPathAttributes(List<BgpValueType> attributes) {
             this.bgpPathAttributes = new BgpPathAttributes(attributes);
             return this;
         }
 
-        @Override
-        public Builder setNlriIdentifier(short afi, byte safi) {
-            this.afi = afi;
-            this.safi = safi;
-            return this;
-        }
     }
 
     public static final Writer WRITER = new Writer();
@@ -240,6 +217,8 @@
         public void write(ChannelBuffer cb, BgpUpdateMsgVer4 message) throws BgpParseException {
 
             int startIndex = cb.writerIndex();
+            short afi = 0;
+            byte safi = 0;
 
             // write common header and get msg length index
             int msgLenIndex = message.bgpHeader.write(cb);
@@ -247,13 +226,34 @@
             if (msgLenIndex <= 0) {
                 throw new BgpParseException("Unable to write message header.");
             }
+            List<BgpValueType> pathAttr = message.bgpPathAttributes.pathAttributes();
+            if (pathAttr != null) {
+                Iterator<BgpValueType> listIterator = pathAttr.iterator();
 
-            if ((message.afi == Constants.AFI_FLOWSPEC_VALUE) && (message.safi == Constants.SAFI_FLOWSPEC_VALUE)) {
-                //unfeasible route length
-                cb.writeShort(0);
+                while (listIterator.hasNext()) {
+                    BgpValueType attr = listIterator.next();
+                    if (attr instanceof MpReachNlri) {
+                        MpReachNlri mpReach = (MpReachNlri) attr;
+                        afi = mpReach.afi();
+                        safi = mpReach.safi();
+                    } else if (attr instanceof MpUnReachNlri) {
+                        MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
+                        afi = mpUnReach.afi();
+                        safi = mpUnReach.safi();
+                    }
+
+                    if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
+                            || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+                        //unfeasible route length
+                        cb.writeShort(0);
+                    }
+                }
+
             }
 
-            // TODO: write path attributes
+            if (message.bgpPathAttributes != null) {
+                message.bgpPathAttributes.write(cb);
+            }
 
             // write UPDATE Object Length
             int length = cb.writerIndex() - startIndex;