[ONOS-4241]Codec for wide community and flow spec

Change-Id: I2dfd6b88c4ae14a02d258a2cdc9ee35b9ff08292
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java
index 337decc..84ce3fd 100644
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java
@@ -19,9 +19,10 @@
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpFactory;
 import org.onosproject.bgpio.protocol.BgpMessage;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecRouteKey;
 import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.attr.WideCommunity;
 
 /**
  * Represents the peer side of an BGP peer.
@@ -124,14 +125,6 @@
     void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException;
 
     /**
-     * Update flow specification RIB for each peer.
-     *
-     * @param pathAttr list of Bgp path attributes
-     * @throws BgpParseException while building flow spec RIB
-     */
-    void buildFlowSpecRib(List<BgpValueType> pathAttr) throws BgpParseException;
-
-    /**
      * Return the BGP session info.
      *
      * @return sessionInfo bgp session info
@@ -142,9 +135,10 @@
      * Updates flow specification rule.
      *
      * @param operType operation type add or delete or update
-     * @param prefix prefix for the flow rule
+     * @param routeKey flow route key  for the flow rule
      * @param flowSpec BGP flow specification components
+     * @param wideCommunity for route policy
      */
-    void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecPrefix prefix,
-                               BgpFlowSpecDetails flowSpec);
+    void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
+                               BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity);
 }
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
deleted file mode 100755
index b2f0511..0000000
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetails.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.bgpio.protocol.flowspec;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import org.onosproject.bgpio.types.BgpValueType;
-import org.onosproject.bgpio.types.RouteDistinguisher;
-import com.google.common.base.MoreObjects;
-
-/**
- * This Class stores flow specification components and action.
- */
-public class BgpFlowSpecDetails {
-    private List<BgpValueType> flowSpecComponents;
-    private List<BgpValueType> fsActionTlv;
-    private RouteDistinguisher routeDistinguisher;
-
-    /**
-     * Flow specification details object constructor with the parameter.
-     *
-     * @param flowSpecComponents flow specification components
-     */
-    public BgpFlowSpecDetails(List<BgpValueType> flowSpecComponents) {
-        this.flowSpecComponents = flowSpecComponents;
-    }
-
-    /**
-     * Flow specification details object constructor.
-     *
-     */
-    public BgpFlowSpecDetails() {
-
-    }
-
-    /**
-     * Returns flow specification action tlv.
-     *
-     * @return flow specification action tlv
-     */
-    public List<BgpValueType> fsActionTlv() {
-        return this.fsActionTlv;
-    }
-
-    /**
-     * Set flow specification action tlv.
-     *
-     * @param fsActionTlv flow specification action tlv
-     */
-    public void setFsActionTlv(List<BgpValueType> fsActionTlv) {
-        this.fsActionTlv = fsActionTlv;
-    }
-
-    /**
-     * Returns route distinguisher for the flow specification components.
-     *
-     * @return route distinguisher for the flow specification components
-     */
-    public RouteDistinguisher routeDistinguisher() {
-        return this.routeDistinguisher;
-    }
-
-    /**
-     * Set route distinguisher for flow specification component.
-     *
-     * @param routeDistinguisher route distinguisher
-     */
-    public void setRouteDistinguiher(RouteDistinguisher routeDistinguisher) {
-        this.routeDistinguisher = routeDistinguisher;
-    }
-
-    /**
-     * Returns flow specification components.
-     *
-     * @return flow specification components
-     */
-    public List<BgpValueType> flowSpecComponents() {
-        return this.flowSpecComponents;
-    }
-
-    /**
-     * Sets flow specification components.
-     *
-     * @param flowSpecComponents flow specification components
-     */
-    public void setFlowSpecComponents(List<BgpValueType> flowSpecComponents) {
-        this.flowSpecComponents = flowSpecComponents;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(flowSpecComponents);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (obj instanceof BgpFlowSpecDetails) {
-            int countObjSubTlv = 0;
-            int countOtherSubTlv = 0;
-            boolean isCommonSubTlv = true;
-            BgpFlowSpecDetails other = (BgpFlowSpecDetails) obj;
-            Iterator<BgpValueType> objListIterator = other.flowSpecComponents.iterator();
-            countOtherSubTlv = other.flowSpecComponents.size();
-            countObjSubTlv = flowSpecComponents.size();
-            if (countObjSubTlv != countOtherSubTlv) {
-                return false;
-            } else {
-                while (objListIterator.hasNext() && isCommonSubTlv) {
-                    BgpValueType subTlv = objListIterator.next();
-                    if (flowSpecComponents.contains(subTlv) && other.flowSpecComponents.contains(subTlv)) {
-                        isCommonSubTlv = Objects.equals(flowSpecComponents.get(flowSpecComponents.indexOf(subTlv)),
-                                            other.flowSpecComponents.get(other.flowSpecComponents.indexOf(subTlv)));
-                    } else {
-                        isCommonSubTlv = false;
-                    }
-                }
-                return isCommonSubTlv;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("flowSpecComponents", flowSpecComponents)
-                .toString();
-    }
-}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecNlri.java
new file mode 100755
index 0000000..fa40149
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecNlri.java
@@ -0,0 +1,293 @@
+/*
+ * 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.bgpio.protocol.flowspec;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.onosproject.bgpio.types.BgpFsDestinationPortNum;
+import org.onosproject.bgpio.types.BgpFsDestinationPrefix;
+import org.onosproject.bgpio.types.BgpFsDscpValue;
+import org.onosproject.bgpio.types.BgpFsFragment;
+import org.onosproject.bgpio.types.BgpFsIcmpCode;
+import org.onosproject.bgpio.types.BgpFsIcmpType;
+import org.onosproject.bgpio.types.BgpFsIpProtocol;
+import org.onosproject.bgpio.types.BgpFsPacketLength;
+import org.onosproject.bgpio.types.BgpFsPortNum;
+import org.onosproject.bgpio.types.BgpFsSourcePortNum;
+import org.onosproject.bgpio.types.BgpFsSourcePrefix;
+import org.onosproject.bgpio.types.BgpFsTcpFlags;
+import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.RouteDistinguisher;
+import org.onosproject.bgpio.util.Constants;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * This Class stores flow specification components and action.
+ */
+public class BgpFlowSpecNlri {
+    private List<BgpValueType> flowSpecComponents;
+    private List<BgpValueType> fsActionTlv;
+    private RouteDistinguisher routeDistinguisher;
+    public static final short FLOW_SPEC_LEN = 240;
+
+    /**
+     * Flow specification details object constructor with the parameter.
+     *
+     * @param flowSpecComponents flow specification components
+     */
+    public BgpFlowSpecNlri(List<BgpValueType> flowSpecComponents) {
+        this.flowSpecComponents = flowSpecComponents;
+    }
+
+    /**
+     * Flow specification details object constructor.
+     *
+     */
+    public BgpFlowSpecNlri() {
+
+    }
+
+    /**
+     * Returns flow specification action tlv.
+     *
+     * @return flow specification action tlv
+     */
+    public List<BgpValueType> fsActionTlv() {
+        return this.fsActionTlv;
+    }
+
+    /**
+     * Set flow specification action tlv.
+     *
+     * @param fsActionTlv flow specification action tlv
+     */
+    public void setFsActionTlv(List<BgpValueType> fsActionTlv) {
+        this.fsActionTlv = fsActionTlv;
+    }
+
+    /**
+     * Returns route distinguisher for the flow specification components.
+     *
+     * @return route distinguisher for the flow specification components
+     */
+    public RouteDistinguisher routeDistinguisher() {
+        return this.routeDistinguisher;
+    }
+
+    /**
+     * Set route distinguisher for flow specification component.
+     *
+     * @param routeDistinguisher route distinguisher
+     */
+    public void setRouteDistinguiher(RouteDistinguisher routeDistinguisher) {
+        this.routeDistinguisher = routeDistinguisher;
+    }
+
+    /**
+     * Returns flow specification components.
+     *
+     * @return flow specification components
+     */
+    public List<BgpValueType> flowSpecComponents() {
+        return this.flowSpecComponents;
+    }
+
+    /**
+     * Sets flow specification components.
+     *
+     * @param flowSpecComponents flow specification components
+     */
+    public void setFlowSpecComponents(List<BgpValueType> flowSpecComponents) {
+        this.flowSpecComponents = flowSpecComponents;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(flowSpecComponents);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof BgpFlowSpecNlri) {
+            int countObjSubTlv = 0;
+            int countOtherSubTlv = 0;
+            boolean isCommonSubTlv = true;
+            BgpFlowSpecNlri other = (BgpFlowSpecNlri) obj;
+            Iterator<BgpValueType> objListIterator = other.flowSpecComponents.iterator();
+            countOtherSubTlv = other.flowSpecComponents.size();
+            countObjSubTlv = flowSpecComponents.size();
+            if (countObjSubTlv != countOtherSubTlv) {
+                return false;
+            } else {
+                while (objListIterator.hasNext() && isCommonSubTlv) {
+                    BgpValueType subTlv = objListIterator.next();
+                    if (flowSpecComponents.contains(subTlv) && other.flowSpecComponents.contains(subTlv)) {
+                        isCommonSubTlv = Objects.equals(flowSpecComponents.get(flowSpecComponents.indexOf(subTlv)),
+                                            other.flowSpecComponents.get(other.flowSpecComponents.indexOf(subTlv)));
+                    } else {
+                        isCommonSubTlv = false;
+                    }
+                }
+                return isCommonSubTlv;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Write flow type to channel buffer.
+     *
+     * @param tlv flow type
+     * @param cb channel buffer
+     */
+    public static void writeFlowType(BgpValueType tlv, ChannelBuffer cb) {
+
+        switch (tlv.getType()) {
+            case Constants.BGP_FLOWSPEC_DST_PREFIX:
+                BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
+                fsDstPrefix.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_SRC_PREFIX:
+                BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
+                fsSrcPrefix.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_IP_PROTO:
+                BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
+                fsIpProtocol.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_PORT:
+                BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
+                fsPortNum.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_DST_PORT:
+                BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
+                fsDstPortNum.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_SRC_PORT:
+                BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
+                fsSrcPortNum.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_ICMP_TP:
+                BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
+                fsIcmpType.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_ICMP_CD:
+                BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
+                fsIcmpCode.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_TCP_FLAGS:
+                BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
+                fsTcpFlags.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_PCK_LEN:
+                BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
+                fsPacketLen.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_DSCP:
+                BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
+                fsDscpVal.write(cb);
+                break;
+            case Constants.BGP_FLOWSPEC_FRAGMENT:
+                BgpFsFragment fsFragment = (BgpFsFragment) tlv;
+                fsFragment.write(cb);
+                break;
+            default:
+                break;
+        }
+        return;
+    }
+
+    /**
+     * Update buffer with identical flow types.
+     *
+     * @param cb channel buffer
+     */
+    public static void updateBufferIdenticalFlowTypes(ChannelBuffer cb, BgpFlowSpecNlri bgpFlowSpecNlri) {
+
+        List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
+        ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+
+        while (listIterator.hasNext()) {
+            ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
+            int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
+
+            BgpValueType tlv = listIterator.next();
+            writeFlowType(tlv, flowSpecTmpBuff);
+
+            /* RFC 5575: section 4,  If the NLRI length value is smaller than 240 (0xf0 hex), the length
+                                     field can be encoded as a single octet.  Otherwise, it is encoded as
+                                     an extended-length 2-octet values */
+            int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
+            if (len >= FLOW_SPEC_LEN) {
+                cb.writeShort(len);
+            } else {
+                cb.writeByte(len);
+            }
+            //Copy from bynamic buffer to channel buffer
+            cb.writeBytes(flowSpecTmpBuff);
+        }
+        return;
+    }
+
+    /**
+     * Update buffer with non-identical flow types.
+     *
+     * @param cb channel buffer
+     */
+    public static void updateBufferNonIdenticalFlowTypes(ChannelBuffer cb, BgpFlowSpecNlri bgpFlowSpecNlri) {
+        ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
+        List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
+        ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+        int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
+
+        flowSpec = bgpFlowSpecNlri.flowSpecComponents();
+        listIterator = flowSpec.listIterator();
+
+        while (listIterator.hasNext()) {
+            BgpValueType tlv = listIterator.next();
+            writeFlowType(tlv, flowSpecTmpBuff);
+        }
+
+        /* RFC 5575: section 4,  If the NLRI length value is smaller than 240 (0xf0 hex), the length
+                                 field can be encoded as a single octet.  Otherwise, it is encoded as
+                                 an extended-length 2-octet values */
+        int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
+        if (len >= FLOW_SPEC_LEN) {
+            cb.writeShort(len);
+        } else {
+            cb.writeByte(len);
+        }
+        //Copy from bynamic buffer to channel buffer
+        cb.writeBytes(flowSpecTmpBuff);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("flowSpecComponents", flowSpecComponents)
+                .toString();
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefix.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefix.java
deleted file mode 100755
index 8373ccf..0000000
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefix.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.bgpio.protocol.flowspec;
-
-import java.util.Objects;
-import org.onlab.packet.IpPrefix;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.nio.ByteBuffer;
-
-import com.google.common.base.MoreObjects;
-
-/**
- * Provides BGP flow specification rule index.
- */
-public class BgpFlowSpecPrefix implements Comparable<Object> {
-
-    private static final Logger log = LoggerFactory.getLogger(BgpFlowSpecPrefix.class);
-
-    private final IpPrefix destinationPrefix;
-    private final IpPrefix sourcePrefix;
-
-    /**
-     * Constructor to initialize parameters.
-     *
-     * @param destinationPrefix destination prefix
-     * @param sourcePrefix source prefix
-     */
-    public BgpFlowSpecPrefix(IpPrefix destinationPrefix, IpPrefix sourcePrefix) {
-        if (destinationPrefix == null) {
-            destinationPrefix = IpPrefix.valueOf(0, 0);
-        }
-
-        if (sourcePrefix == null) {
-            sourcePrefix = IpPrefix.valueOf(0, 0);
-        }
-
-        this.destinationPrefix = destinationPrefix;
-        this.sourcePrefix = sourcePrefix;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(destinationPrefix, sourcePrefix);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (obj instanceof BgpFlowSpecPrefix) {
-             BgpFlowSpecPrefix other = (BgpFlowSpecPrefix) obj;
-
-             if ((this.destinationPrefix != null) && (this.sourcePrefix != null)
-                 && (this.destinationPrefix.equals(other.destinationPrefix))) {
-                 return this.sourcePrefix.equals(other.sourcePrefix);
-             } else if (this.destinationPrefix != null) {
-                 return this.destinationPrefix.equals(other.destinationPrefix);
-             } else if (this.sourcePrefix != null) {
-                 return this.sourcePrefix.equals(other.sourcePrefix);
-             }
-             return false;
-        }
-        return false;
-    }
-
-    /**
-     * Returns destination prefix.
-     *
-     * @return destination prefix
-     */
-    public IpPrefix destinationPrefix() {
-        return this.destinationPrefix;
-    }
-
-    /**
-     * Returns source prefix.
-     *
-     * @return source prefix
-     */
-    public IpPrefix sourcePrefix() {
-        return this.sourcePrefix;
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass()).omitNullValues()
-                .add("destinationPrefix", destinationPrefix)
-                .add("sourcePrefix", destinationPrefix)
-                .toString();
-    }
-
-    /**
-     * Compares this and o object.
-     *
-     * @param o object to be compared with this object
-     * @return which object is greater
-     */
-    public int compareTo(Object o) {
-        if (this.equals(o)) {
-            return 0;
-        }
-
-        if (o instanceof BgpFlowSpecPrefix) {
-            BgpFlowSpecPrefix that = (BgpFlowSpecPrefix) o;
-            if (this.destinationPrefix() != null) {
-                if (this.destinationPrefix().prefixLength() == that.destinationPrefix().prefixLength()) {
-                    ByteBuffer value1 = ByteBuffer.wrap(this.destinationPrefix().address().toOctets());
-                    ByteBuffer value2 = ByteBuffer.wrap(that.destinationPrefix().address().toOctets());
-                    int cmpVal = value1.compareTo(value2);
-                    if (cmpVal != 0) {
-                        return cmpVal;
-                    }
-                } else {
-                    if (this.destinationPrefix().prefixLength() > that.destinationPrefix().prefixLength()) {
-                        return 1;
-                    } else if (this.destinationPrefix().prefixLength() < that.destinationPrefix().prefixLength()) {
-                        return -1;
-                    }
-                }
-            }
-            if (this.sourcePrefix() != null) {
-                if (this.sourcePrefix().prefixLength() == that.sourcePrefix().prefixLength()) {
-                    ByteBuffer value1 = ByteBuffer.wrap(this.sourcePrefix().address().toOctets());
-                    ByteBuffer value2 = ByteBuffer.wrap(that.sourcePrefix().address().toOctets());
-                    return value1.compareTo(value2);
-                }
-
-                if (this.sourcePrefix().prefixLength() > that.sourcePrefix().prefixLength()) {
-                    return 1;
-                } else if (this.sourcePrefix().prefixLength() < that.sourcePrefix().prefixLength()) {
-                    return -1;
-                }
-            }
-            return 0;
-        }
-        return 1;
-    }
-}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecRouteKey.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecRouteKey.java
new file mode 100755
index 0000000..4da44aa
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecRouteKey.java
@@ -0,0 +1,91 @@
+/*
+ * 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.bgpio.protocol.flowspec;
+
+import java.util.Objects;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides BGP flow specification route index.
+ */
+public class BgpFlowSpecRouteKey implements Comparable<Object> {
+
+    private static final Logger log = LoggerFactory.getLogger(BgpFlowSpecRouteKey.class);
+
+    private final String routeKey;
+
+    /**
+     * Constructor to initialize parameters.
+     *
+     * @param routeKey route key
+     */
+    public BgpFlowSpecRouteKey(String routeKey) {
+        this.routeKey = routeKey;
+    }
+
+    /**
+     * Returns route key.
+     *
+     * @return route key
+     */
+    public String routeKey() {
+        return this.routeKey;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(routeKey);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BgpFlowSpecRouteKey) {
+            BgpFlowSpecRouteKey other = (BgpFlowSpecRouteKey) obj;
+            return this.routeKey.equals(other.routeKey);
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        if (this.equals(o)) {
+            return 0;
+        }
+
+        if (o instanceof BgpFlowSpecRouteKey) {
+            BgpFlowSpecRouteKey other = (BgpFlowSpecRouteKey) o;
+            if (this.routeKey.compareTo(other.routeKey) != 0) {
+                return this.routeKey.compareTo(other.routeKey);
+            }
+            return 0;
+        }
+        return 1;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).omitNullValues()
+                .add("routeKey", routeKey)
+                .toString();
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
index c0f6d35..12c3c62 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
@@ -22,11 +22,10 @@
 import java.util.ListIterator;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
 import org.onlab.packet.Ip4Address;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
@@ -46,14 +45,13 @@
     public static final byte MPREACHNLRI_TYPE = 14;
     public static final byte LINK_NLRITYPE = 2;
     public static final byte FLAGS = (byte) 0x90;
-    public static final short FLOW_SPEC_LEN = 240;
     private boolean isMpReachNlri = false;
     private final List<BgpLSNlri> mpReachNlri;
     private final int length;
     private final short afi;
     private final byte safi;
     private final Ip4Address ipNextHop;
-    private BgpFlowSpecDetails bgpFlowSpecInfo;
+    private BgpFlowSpecNlri bgpFlowSpecNlri;
 
     /**
      * Constructor to initialize parameters.
@@ -73,12 +71,12 @@
         this.length = length;
     }
 
-    public MpReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
+    public MpReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
         this.mpReachNlri = null;
         this.isMpReachNlri = true;
         this.length = 0;
         this.ipNextHop = null;
-        this.bgpFlowSpecInfo = bgpFlowSpecInfo;
+        this.bgpFlowSpecNlri = bgpFlowSpecNlri;
         this.afi = afi;
         this.safi = safi;
     }
@@ -115,8 +113,8 @@
      *
      * @return BGP flow specification info
      */
-    public BgpFlowSpecDetails bgpFlowSpecInfo() {
-        return this.bgpFlowSpecInfo;
+    public BgpFlowSpecNlri bgpFlowSpecNlri() {
+        return this.bgpFlowSpecNlri;
     }
 
     /**
@@ -208,64 +206,70 @@
                         routeDistinguisher = new RouteDistinguisher();
                         routeDistinguisher = RouteDistinguisher.read(tempCb);
                     }
-                    short totNlriLen = tempCb.getByte(tempCb.readerIndex());
-                    if (totNlriLen >= FLOW_SPEC_LEN) {
-                        totNlriLen = tempCb.readShort();
-                    } else {
-                        totNlriLen = tempCb.readByte();
-                    }
-                    if (tempCb.readableBytes() < totNlriLen) {
-                        Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
-                                BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
-                    }
-                    tempBuf = tempCb.readBytes(totNlriLen);
-                    while (tempBuf.readableBytes() > 0) {
-                        short type = tempBuf.readByte();
-                        switch (type) {
-                        case Constants.BGP_FLOWSPEC_DST_PREFIX:
-                            flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_SRC_PREFIX:
-                            flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_IP_PROTO:
-                            flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_PORT:
-                            flowSpecComponent = BgpFsPortNum.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_DST_PORT:
-                            flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_SRC_PORT:
-                            flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_ICMP_TP:
-                            flowSpecComponent = BgpFsIcmpType.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_ICMP_CD:
-                            flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_TCP_FLAGS:
-                            flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_PCK_LEN:
-                            flowSpecComponent = BgpFsPacketLength.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_DSCP:
-                            flowSpecComponent = BgpFsDscpValue.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_FRAGMENT:
-                            flowSpecComponent = BgpFsFragment.read(tempBuf);
-                            break;
-                        default:
-                            log.debug("flow spec type not supported" + type);
-                            break;
+                    while (tempCb.readableBytes() > 0) {
+                        short totNlriLen = tempCb.getByte(tempCb.readerIndex());
+                        if (totNlriLen >= BgpFlowSpecNlri.FLOW_SPEC_LEN) {
+                           if (tempCb.readableBytes() < 2) {
+                                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                    BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
+                            }
+                            totNlriLen = tempCb.readShort();
+                        } else {
+                            totNlriLen = tempCb.readByte();
                         }
-                        flowSpecComponents.add(flowSpecComponent);
+                        if (tempCb.readableBytes() < totNlriLen) {
+                            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                    BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
+                        }
+                        tempBuf = tempCb.readBytes(totNlriLen);
+                        while (tempBuf.readableBytes() > 0) {
+                            short type = tempBuf.readByte();
+                            switch (type) {
+                            case Constants.BGP_FLOWSPEC_DST_PREFIX:
+                                flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_SRC_PREFIX:
+                                flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_IP_PROTO:
+                                flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_PORT:
+                                flowSpecComponent = BgpFsPortNum.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_DST_PORT:
+                                flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_SRC_PORT:
+                                flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_ICMP_TP:
+                                flowSpecComponent = BgpFsIcmpType.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_ICMP_CD:
+                                flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_TCP_FLAGS:
+                                flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_PCK_LEN:
+                                flowSpecComponent = BgpFsPacketLength.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_DSCP:
+                                flowSpecComponent = BgpFsDscpValue.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_FRAGMENT:
+                                flowSpecComponent = BgpFsFragment.read(tempBuf);
+                                break;
+                            default:
+                                log.debug("flow spec type not supported" + type);
+                                break;
+                            }
+                            flowSpecComponents.add(flowSpecComponent);
+                        }
                     }
                 }
-                BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
+                BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
                 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
                 return new MpReachNlri(flowSpecDetails, afi, safi);
             } else {
@@ -310,8 +314,12 @@
     @Override
     public int write(ChannelBuffer cb) {
         int iLenStartIndex = cb.writerIndex();
+
         if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
             || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+            List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
+            ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+            boolean isAllFlowTypesIdentical = true;
 
             cb.writeByte(FLAGS);
             cb.writeByte(MPREACHNLRI_TYPE);
@@ -326,84 +334,27 @@
             //sub network points of attachment
             cb.writeByte(0);
 
-            if (bgpFlowSpecInfo.routeDistinguisher() != null) {
-                cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
+            if (bgpFlowSpecNlri.routeDistinguisher() != null) {
+                cb.writeLong(bgpFlowSpecNlri.routeDistinguisher().getRouteDistinguisher());
             }
 
-            ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
-            int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
-
-            List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
-            ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
-
+            BgpValueType tlv1 = null;
+            if (listIterator.hasNext()) {
+                tlv1 = listIterator.next();
+            }
             while (listIterator.hasNext()) {
                 BgpValueType tlv = listIterator.next();
-                switch (tlv.getType()) {
-                case Constants.BGP_FLOWSPEC_DST_PREFIX:
-                    BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
-                    fsDstPrefix.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_SRC_PREFIX:
-                    BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
-                    fsSrcPrefix.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_IP_PROTO:
-                    BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
-                    fsIpProtocol.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_PORT:
-                    BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
-                    fsPortNum.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_DST_PORT:
-                    BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
-                    fsDstPortNum.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_SRC_PORT:
-                    BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
-                    fsSrcPortNum.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_ICMP_TP:
-                    BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
-                    fsIcmpType.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_ICMP_CD:
-                    BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
-                    fsIcmpCode.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_TCP_FLAGS:
-                    BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
-                    fsTcpFlags.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_PCK_LEN:
-                    BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
-                    fsPacketLen.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_DSCP:
-                    BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
-                    fsDscpVal.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_FRAGMENT:
-                    BgpFsFragment fsFragment = (BgpFsFragment) tlv;
-                    fsFragment.write(flowSpecTmpBuff);
-                    break;
-                default:
+                if (tlv.getType() != tlv1.getType()) {
+                    isAllFlowTypesIdentical = false;
                     break;
                 }
             }
 
-            /* RFC 5575: section 4,  If the NLRI length value is smaller than 240 (0xf0 hex), the length
-                                     field can be encoded as a single octet.  Otherwise, it is encoded as
-                                     an extended-length 2-octet values */
-            int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
-            if (len >= FLOW_SPEC_LEN) {
-                cb.writeShort(len);
+            if (isAllFlowTypesIdentical) {
+                BgpFlowSpecNlri.updateBufferIdenticalFlowTypes(cb, bgpFlowSpecNlri());
             } else {
-                cb.writeByte(len);
+                BgpFlowSpecNlri.updateBufferNonIdenticalFlowTypes(cb, bgpFlowSpecNlri());
             }
-            //Copy from bynamic buffer to channel buffer
-            cb.writeBytes(flowSpecTmpBuff);
-
             int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
             cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
 
@@ -416,7 +367,7 @@
     public String toString() {
         return MoreObjects.toStringHelper(getClass()).omitNullValues()
                 .add("mpReachNlri", mpReachNlri)
-                .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
+                .add("bgpFlowSpecNlri", bgpFlowSpecNlri)
                 .add("afi", afi)
                 .add("safi", safi)
                 .add("ipNextHop", ipNextHop)
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
index cb871a6..ebeef61 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
@@ -21,10 +21,9 @@
 import java.util.ListIterator;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
@@ -44,13 +43,12 @@
     public static final byte MPUNREACHNLRI_TYPE = 15;
     public static final byte LINK_NLRITYPE = 2;
     public static final byte FLAGS = (byte) 0x90;
-    public static final short FLOW_SPEC_LEN = 240;
     private boolean isMpUnReachNlri = false;
     private final short afi;
     private final byte safi;
     private final List<BgpLSNlri> mpUnReachNlri;
     private final int length;
-    private BgpFlowSpecDetails bgpFlowSpecInfo;
+    private BgpFlowSpecNlri bgpFlowSpecNlri;
 
     /**
      * Constructor to initialize parameters.
@@ -69,11 +67,11 @@
         this.length = length;
     }
 
-    public MpUnReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
+    public MpUnReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
         this.mpUnReachNlri = null;
         this.isMpUnReachNlri = true;
         this.length = 0;
-        this.bgpFlowSpecInfo = bgpFlowSpecInfo;
+        this.bgpFlowSpecNlri = bgpFlowSpecNlri;
         this.afi = afi;
         this.safi = safi;
     }
@@ -83,8 +81,8 @@
      *
      * @return BGP flow specification info
      */
-    public BgpFlowSpecDetails bgpFlowSpecInfo() {
-        return this.bgpFlowSpecInfo;
+    public BgpFlowSpecNlri bgpFlowSpecNlri() {
+        return this.bgpFlowSpecNlri;
     }
 
     /**
@@ -162,64 +160,70 @@
                         routeDistinguisher = new RouteDistinguisher();
                         routeDistinguisher = RouteDistinguisher.read(tempCb);
                     }
-                    short totNlriLen = tempCb.getByte(tempCb.readerIndex());
-                    if (totNlriLen >= FLOW_SPEC_LEN) {
-                        totNlriLen = tempCb.readShort();
-                    } else {
-                        totNlriLen = tempCb.readByte();
-                    }
-                    if (tempCb.readableBytes() < totNlriLen) {
-                        Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
-                                BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
-                    }
-                    tempBuf = tempCb.readBytes(totNlriLen);
-                    while (tempBuf.readableBytes() > 0) {
-                        short type = tempBuf.readByte();
-                        switch (type) {
-                        case Constants.BGP_FLOWSPEC_DST_PREFIX:
-                            flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_SRC_PREFIX:
-                            flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_IP_PROTO:
-                            flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_PORT:
-                            flowSpecComponent = BgpFsPortNum.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_DST_PORT:
-                            flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_SRC_PORT:
-                            flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_ICMP_TP:
-                            flowSpecComponent = BgpFsIcmpType.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_ICMP_CD:
-                            flowSpecComponent = BgpFsIcmpType.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_TCP_FLAGS:
-                            flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_PCK_LEN:
-                            flowSpecComponent = BgpFsPacketLength.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_DSCP:
-                            flowSpecComponent = BgpFsDscpValue.read(tempBuf);
-                            break;
-                        case Constants.BGP_FLOWSPEC_FRAGMENT:
-                            flowSpecComponent = BgpFsFragment.read(tempBuf);
-                            break;
-                        default:
-                            log.debug("flow spec type not supported" + type);
-                            break;
+                    while (tempCb.readableBytes() > 0) {
+                        short totNlriLen = tempCb.getByte(tempCb.readerIndex());
+                        if (totNlriLen >= BgpFlowSpecNlri.FLOW_SPEC_LEN) {
+                           if (tempCb.readableBytes() < 2) {
+                                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                    BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
+                            }
+                            totNlriLen = tempCb.readShort();
+                        } else {
+                            totNlriLen = tempCb.readByte();
                         }
-                        flowSpecComponents.add(flowSpecComponent);
+                        if (tempCb.readableBytes() < totNlriLen) {
+                            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                    BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
+                        }
+                        tempBuf = tempCb.readBytes(totNlriLen);
+                        while (tempBuf.readableBytes() > 0) {
+                            short type = tempBuf.readByte();
+                            switch (type) {
+                            case Constants.BGP_FLOWSPEC_DST_PREFIX:
+                                flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_SRC_PREFIX:
+                                flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_IP_PROTO:
+                                flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_PORT:
+                                flowSpecComponent = BgpFsPortNum.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_DST_PORT:
+                                flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_SRC_PORT:
+                                flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_ICMP_TP:
+                                flowSpecComponent = BgpFsIcmpType.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_ICMP_CD:
+                                flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_TCP_FLAGS:
+                                flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_PCK_LEN:
+                                flowSpecComponent = BgpFsPacketLength.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_DSCP:
+                                flowSpecComponent = BgpFsDscpValue.read(tempBuf);
+                                break;
+                            case Constants.BGP_FLOWSPEC_FRAGMENT:
+                                flowSpecComponent = BgpFsFragment.read(tempBuf);
+                                break;
+                            default:
+                                log.debug("flow spec type not supported" + type);
+                                break;
+                            }
+                            flowSpecComponents.add(flowSpecComponent);
+                        }
                     }
                 }
-                BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
+                BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
                 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
                 return new MpUnReachNlri(flowSpecDetails, afi, safi);
             } else {
@@ -286,6 +290,9 @@
         int iLenStartIndex = cb.writerIndex();
         if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE) ||
             (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+            List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
+            ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+            boolean isAllFlowTypesIdentical = true;
 
             cb.writeByte(FLAGS);
             cb.writeByte(MPUNREACHNLRI_TYPE);
@@ -296,79 +303,27 @@
             cb.writeShort(afi);
             cb.writeByte(safi);
 
-            if (bgpFlowSpecInfo.routeDistinguisher() != null) {
-                cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
+            if (bgpFlowSpecNlri.routeDistinguisher() != null) {
+                cb.writeLong(bgpFlowSpecNlri.routeDistinguisher().getRouteDistinguisher());
             }
 
-            ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
-            int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
-
-            List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
-            ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+            BgpValueType tlv1 = null;
+            if (listIterator.hasNext()) {
+                tlv1 = listIterator.next();
+            }
             while (listIterator.hasNext()) {
                 BgpValueType tlv = listIterator.next();
-                switch (tlv.getType()) {
-                case Constants.BGP_FLOWSPEC_DST_PREFIX:
-                    BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
-                    fsDstPrefix.write(flowSpecTmpBuff);
+                if (tlv.getType() != tlv1.getType()) {
+                    isAllFlowTypesIdentical = false;
                     break;
-                case Constants.BGP_FLOWSPEC_SRC_PREFIX:
-                    BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
-                    fsSrcPrefix.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_IP_PROTO:
-                    BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
-                    fsIpProtocol.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_PORT:
-                    BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
-                    fsPortNum.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_DST_PORT:
-                    BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
-                    fsDstPortNum.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_SRC_PORT:
-                    BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
-                    fsSrcPortNum.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_ICMP_TP:
-                    BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
-                    fsIcmpType.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_ICMP_CD:
-                    BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
-                    fsIcmpCode.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_TCP_FLAGS:
-                    BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
-                    fsTcpFlags.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_PCK_LEN:
-                    BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
-                    fsPacketLen.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_DSCP:
-                    BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
-                    fsDscpVal.write(flowSpecTmpBuff);
-                    break;
-                case Constants.BGP_FLOWSPEC_FRAGMENT:
-                    BgpFsFragment fsFragment = (BgpFsFragment) tlv;
-                    fsFragment.write(flowSpecTmpBuff);
-                    break;
-                default:
                 }
             }
 
-            int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
-            if (len >= FLOW_SPEC_LEN) {
-                cb.writeShort(len);
+            if (isAllFlowTypesIdentical) {
+                BgpFlowSpecNlri.updateBufferIdenticalFlowTypes(cb, bgpFlowSpecNlri());
             } else {
-                cb.writeByte(len);
+                BgpFlowSpecNlri.updateBufferNonIdenticalFlowTypes(cb, bgpFlowSpecNlri());
             }
-            //Copy from bynamic buffer to channel buffer
-            cb.writeBytes(flowSpecTmpBuff);
-
             int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
             cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
         }
@@ -386,7 +341,7 @@
     public String toString() {
         return MoreObjects.toStringHelper(getClass()).omitNullValues()
                 .add("mpReachNlri", mpUnReachNlri)
-                .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
+                .add("bgpFlowSpecNlri", bgpFlowSpecNlri)
                 .add("afi", afi)
                 .add("safi", safi)
                 .add("length", length)
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RpdCapabilityTlv.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RpdCapabilityTlv.java
index 1542d33..fa7f6d4 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RpdCapabilityTlv.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RpdCapabilityTlv.java
@@ -64,6 +64,22 @@
         return sendReceive;
     }
 
+    /**
+     * Returns address family identifier value.
+     * @return afi address family identifier value
+     */
+    public short getAfi() {
+        return afi;
+    }
+
+    /**
+     * Returns subsequent address family identifier value.
+     * @return safi subsequent address family identifier value
+     */
+    public byte getSafi() {
+        return sAfi;
+    }
+
     @Override
     public short getType() {
         return TYPE;
diff --git a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetailsTest.java b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecNlriTest.java
similarity index 89%
rename from protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetailsTest.java
rename to protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecNlriTest.java
index ea897e2..c42fd02 100644
--- a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecDetailsTest.java
+++ b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecNlriTest.java
@@ -28,23 +28,23 @@
 import com.google.common.testing.EqualsTester;
 
 /**
- * Test for BgpFlowSpecDetails flow specification.
+ * Test for BgpFlowSpecNlri flow specification.
  */
-public class BgpFlowSpecDetailsTest {
+public class BgpFlowSpecNlriTest {
 
     List<BgpValueType> flowSpecComponents1 = new LinkedList<>();
     private List<BgpFsOperatorValue> operatorValue1 = new ArrayList<>();
-    BgpFlowSpecDetails flowSpecDetails1 = new BgpFlowSpecDetails(flowSpecComponents1);
+    BgpFlowSpecNlri flowSpecDetails1 = new BgpFlowSpecNlri(flowSpecComponents1);
     BgpFsPortNum portNum1 = new BgpFsPortNum(operatorValue1);
 
     List<BgpValueType> flowSpecComponents = new LinkedList<>();
     private List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
-    BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
+    BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
     BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
 
     List<BgpValueType> flowSpecComponents2 = new LinkedList<>();
     private List<BgpFsOperatorValue> operatorValue2 = new ArrayList<>();
-    BgpFlowSpecDetails flowSpecDetails2 = new BgpFlowSpecDetails(flowSpecComponents2);
+    BgpFlowSpecNlri flowSpecDetails2 = new BgpFlowSpecNlri(flowSpecComponents2);
     BgpFsPortNum portNum2 = new BgpFsPortNum(operatorValue2);
 
     @Test
diff --git a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefixTest.java b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefixTest.java
index 9cc8cf5..0d7fc2e 100644
--- a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefixTest.java
+++ b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecPrefixTest.java
@@ -16,23 +16,18 @@
 package org.onosproject.bgpio.protocol.flowspec;
 
 import org.junit.Test;
-
-import org.onlab.packet.IpPrefix;
-
 import com.google.common.testing.EqualsTester;
 
 /**
  * Test for BgpFsDestinationPrefix flow specification component.
  */
 public class BgpFlowSpecPrefixTest {
-    private IpPrefix destinationPrefix1 = IpPrefix.valueOf("21.21.21.21/16");
-    private IpPrefix sourcePrefix1 = IpPrefix.valueOf("11.11.11.11/16");
-    private IpPrefix destinationPrefix2 = IpPrefix.valueOf("42.42.42.42/16");
-    private IpPrefix sourcePrefix2 = IpPrefix.valueOf("32.32.32.32/16");
+    private String routeKey1 = "flowRoute1";
+    private String routeKey2 = "flowRoute2";
 
-    private final BgpFlowSpecPrefix tlv1 = new BgpFlowSpecPrefix(destinationPrefix1, sourcePrefix1);
-    private final BgpFlowSpecPrefix sameAsTlv1 = new BgpFlowSpecPrefix(destinationPrefix1, sourcePrefix1);
-    private final BgpFlowSpecPrefix tlv2 = new BgpFlowSpecPrefix(destinationPrefix2, sourcePrefix2);
+    private final BgpFlowSpecRouteKey tlv1 = new BgpFlowSpecRouteKey(routeKey1);
+    private final BgpFlowSpecRouteKey sameAsTlv1 = new BgpFlowSpecRouteKey(routeKey1);
+    private final BgpFlowSpecRouteKey tlv2 = new BgpFlowSpecRouteKey(routeKey2);
 
     @Test
     public void testEquality() {
diff --git a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecRouteKeyTest.java b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecRouteKeyTest.java
new file mode 100644
index 0000000..76e8162
--- /dev/null
+++ b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/protocol/flowspec/BgpFlowSpecRouteKeyTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.bgpio.protocol.flowspec;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for BgpFlowSpecRouteKeyTest flow specification component.
+ */
+public class BgpFlowSpecRouteKeyTest {
+    private static String routeKey1 = "flowRoute1";
+    private static String routeKey2 = "flowRoute2";
+
+    private final BgpFlowSpecRouteKey tlv1 = new BgpFlowSpecRouteKey(routeKey1);
+    private final BgpFlowSpecRouteKey sameAsTlv1 = new BgpFlowSpecRouteKey(routeKey1);
+    private final BgpFlowSpecRouteKey tlv2 = new BgpFlowSpecRouteKey(routeKey2);
+
+    @Test
+    public void testEquality() {
+        new EqualsTester()
+        .addEqualityGroup(tlv1, sameAsTlv1)
+        .addEqualityGroup(tlv2)
+        .testEquals();
+    }
+}
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
index 85087fb..83c0648 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
@@ -133,29 +133,23 @@
             }
             Iterator<BgpValueType> listIterator = pathAttr.iterator();
             boolean isLinkstate = false;
-            boolean isFlowSpec = false;
+
             while (listIterator.hasNext()) {
                 BgpValueType attr = listIterator.next();
                 if (attr instanceof MpReachNlri) {
                     MpReachNlri mpReach = (MpReachNlri) attr;
-                    if (mpReach.bgpFlowSpecInfo() == null) {
+                    if (mpReach.bgpFlowSpecNlri() == null) {
                         isLinkstate = true;
-                    } else {
-                        isFlowSpec = true;
                     }
                 } else if (attr instanceof MpUnReachNlri) {
                     MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
-                    if (mpUnReach.bgpFlowSpecInfo() == null) {
+                    if (mpUnReach.bgpFlowSpecNlri() == null) {
                         isLinkstate = true;
-                    } else {
-                        isFlowSpec = true;
                     }
                 }
             }
             if (isLinkstate) {
                 peer.buildAdjRibIn(pathAttr);
-            } else if (isFlowSpec) {
-                peer.buildFlowSpecRib(pathAttr);
             }
             break;
         default:
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpFlowSpecRib.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpFlowSpecRib.java
deleted file mode 100755
index 636249c..0000000
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpFlowSpecRib.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.bgp.controller.impl;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.onosproject.bgpio.types.RouteDistinguisher;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
-
-import com.google.common.base.MoreObjects;
-
-/**
- * Implementation of BGP flow specification RIB.
- */
-public class BgpFlowSpecRib {
-    private Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> flowSpecTree = new TreeMap<>();
-    private Map<RouteDistinguisher, Map<BgpFlowSpecPrefix, BgpFlowSpecDetails>> vpnFlowSpecTree = new TreeMap<>();
-
-    /**
-     * Returns the BGP flow spec info.
-     *
-     * @return BGP flow spec tree
-     */
-    public Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> flowSpecTree() {
-        return flowSpecTree;
-    }
-
-    /**
-     * Gets VPN flowspec tree.
-     *
-     * @return vpn flow spec tree
-     */
-    public Map<RouteDistinguisher, Map<BgpFlowSpecPrefix, BgpFlowSpecDetails>> vpnFlowSpecTree() {
-        return vpnFlowSpecTree;
-    }
-
-
-    /**
-     * Update BGP flow spec details.
-     *
-     * @param prefix prefix Info
-     * @param flowSpec BGP flow specifications details
-     */
-    public void add(BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
-        if (flowSpecTree.containsKey(prefix)) {
-            flowSpecTree.replace(prefix, flowSpec);
-        } else {
-            flowSpecTree.put(prefix, flowSpec);
-        }
-    }
-
-    /**
-     * Removes flow spec.
-     *
-     * @param flowSpec BGP flow specification
-     */
-    public void delete(BgpFlowSpecPrefix flowSpec) {
-        if (flowSpecTree.containsKey(flowSpec)) {
-            flowSpecTree.remove(flowSpec);
-        }
-    }
-
-    /**
-     * Update BGP flow spec details with routedistinguisher.
-     *
-     * @param routeDistinguisher route distinguisher
-     * @param prefix prefix Info
-     * @param flowSpec BGP flow specifications details
-     */
-    public void add(RouteDistinguisher routeDistinguisher, BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
-        Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree;
-        if (!vpnFlowSpecTree.containsKey(routeDistinguisher)) {
-
-            fsTree = new TreeMap<>();
-
-            vpnFlowSpecTree.put(routeDistinguisher, fsTree);
-        } else {
-            fsTree = vpnFlowSpecTree().get(routeDistinguisher);
-        }
-        if (fsTree.containsKey(prefix)) {
-            fsTree.replace(prefix, flowSpec);
-        } else {
-            fsTree.put(prefix, flowSpec);
-        }
-    }
-
-    /**
-     * Removes flow spec.
-     *
-     * @param routeDistinguisher route distinguisher
-     * @param flowSpecPrefix BGP flow specification prefix
-     */
-    public void delete(RouteDistinguisher routeDistinguisher, BgpFlowSpecPrefix flowSpecPrefix) {
-        if (vpnFlowSpecTree.containsKey(routeDistinguisher)) {
-            Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree = vpnFlowSpecTree().get(routeDistinguisher);
-            fsTree.remove(flowSpecPrefix);
-            if (fsTree.size() == 0) {
-                vpnFlowSpecTree.remove(routeDistinguisher);
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .omitNullValues()
-                .add("flowSpecTree", flowSpecTree)
-                .add("vpnFlowSpecTree", vpnFlowSpecTree)
-                .toString();
-    }
-}
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
index de2c945..3d14465 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
@@ -19,14 +19,8 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
-
 import org.jboss.netty.channel.Channel;
 import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
 import org.onosproject.bgp.controller.BgpController;
 import org.onosproject.bgp.controller.BgpLocalRib;
 import org.onosproject.bgp.controller.BgpPeer;
@@ -36,8 +30,8 @@
 import org.onosproject.bgpio.protocol.BgpFactory;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
 import org.onosproject.bgpio.protocol.BgpMessage;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecRouteKey;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
@@ -45,8 +39,6 @@
 import org.onosproject.bgpio.types.AsPath;
 import org.onosproject.bgpio.types.As4Path;
 import org.onosproject.bgpio.types.BgpExtendedCommunity;
-import org.onosproject.bgpio.types.BgpFsDestinationPrefix;
-import org.onosproject.bgpio.types.BgpFsSourcePrefix;
 import org.onosproject.bgpio.types.BgpValueType;
 import org.onosproject.bgpio.types.LocalPref;
 import org.onosproject.bgpio.types.Med;
@@ -54,14 +46,17 @@
 import org.onosproject.bgpio.types.MpUnReachNlri;
 import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
 import org.onosproject.bgpio.types.Origin;
-import org.onosproject.bgpio.types.RouteDistinguisher;
+import org.onosproject.bgpio.types.attr.WideCommunity;
+import org.onosproject.bgpio.types.RpdCapabilityTlv;
 import org.onosproject.bgpio.util.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.concurrent.RejectedExecutionException;
@@ -86,26 +81,6 @@
     private BgpLocalRib bgplocalRibVpn;
     private AdjRibIn adjRib;
     private VpnAdjRibIn vpnAdjRib;
-    private BgpFlowSpecRib flowSpecRibOut;
-    private BgpFlowSpecRib flowSpecRibIn;
-
-    /**
-     * Returns the flowSpec RIB out.
-     *
-     * @return flow Specification RIB out
-     */
-    public BgpFlowSpecRib flowSpecRibOut() {
-        return flowSpecRibOut;
-    }
-
-    /**
-     * Returns the flowSpec RIB-in.
-     *
-     * @return flow Specification RIB-in
-     */
-    public BgpFlowSpecRib flowSpecRibIn() {
-        return flowSpecRibIn;
-    }
 
     /**
      * Return the adjacency RIB-IN.
@@ -145,8 +120,6 @@
         this.bgplocalRibVpn =  bgpController.bgpLocalRibVpn();
         this.adjRib = new AdjRibIn();
         this.vpnAdjRib = new VpnAdjRibIn();
-        this.flowSpecRibOut = new BgpFlowSpecRib();
-        this.flowSpecRibIn = new BgpFlowSpecRib();
     }
 
     /**
@@ -171,6 +144,11 @@
                     if ((temp.getAfi() == afi) && (temp.getSafi() == sAfi)) {
                         return true;
                     }
+                } else if (tlv.getType() == RpdCapabilityTlv.TYPE) {
+                    RpdCapabilityTlv temp = (RpdCapabilityTlv) tlv;
+                    if ((temp.getAfi() == afi) && (temp.getSafi() == sAfi)) {
+                        return true;
+                    }
                 }
             }
         }
@@ -182,12 +160,14 @@
      *
      * @param operType operation type
      * @param flowSpec flow specification details
+      * @param wideCommunity for route policy
      */
-    public final void sendFlowSpecUpdateMessageToPeer(FlowSpecOperation operType, BgpFlowSpecDetails flowSpec) {
+    public final void sendFlowSpecUpdateMessageToPeer(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
+                                                      BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity) {
 
         List<BgpValueType> attributesList = new LinkedList<>();
         byte sessionType = sessionInfo.isIbgpSession() ? (byte) 0 : (byte) 1;
-        byte sAfi = Constants.SAFI_FLOWSPEC_VALUE;
+        byte sAfi = Constants.VPN_SAFI_FLOWSPEC_VALUE;
 
         boolean isFsCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
                                                         Constants.AFI_FLOWSPEC_VALUE,
@@ -196,16 +176,26 @@
         boolean isVpnFsCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
                                                         Constants.AFI_FLOWSPEC_VALUE,
                                                         Constants.VPN_SAFI_FLOWSPEC_VALUE);
-        if ((!isFsCapabilitySet) && (!isVpnFsCapabilitySet)) {
+
+        boolean isRpdCapabilitySet = isCapabilitySupported(RpdCapabilityTlv.TYPE,
+                                                        Constants.AFI_FLOWSPEC_RPD_VALUE,
+                                                        Constants.SAFI_FLOWSPEC_RPD_VALUE);
+
+        boolean isVpnRpdCapabilitySet = isCapabilitySupported(RpdCapabilityTlv.TYPE,
+                                                        Constants.AFI_FLOWSPEC_RPD_VALUE,
+                                                        Constants.VPN_SAFI_FLOWSPEC_RDP_VALUE);
+
+        if ((!isFsCapabilitySet) && (!isVpnFsCapabilitySet) && (!isRpdCapabilitySet) && (!isVpnRpdCapabilitySet)) {
             log.debug("Peer do not support BGP flow spec capability", channel.getRemoteAddress());
             return;
         }
 
-        if (isVpnFsCapabilitySet) {
+        if ((wideCommunity != null) && (isVpnRpdCapabilitySet)) {
+            sAfi = Constants.VPN_SAFI_FLOWSPEC_RDP_VALUE;
+        } else if (isVpnFsCapabilitySet) {
             sAfi = Constants.VPN_SAFI_FLOWSPEC_VALUE;
         }
-
-        attributesList.add(new Origin(sessionType));
+        attributesList.add(new Origin((byte) 0));
 
         if (sessionType != 0) {
             // EBGP
@@ -232,6 +222,7 @@
         }
 
         attributesList.add(new BgpExtendedCommunity(flowSpec.fsActionTlv()));
+        attributesList.add(wideCommunity);
 
         if (operType == FlowSpecOperation.ADD) {
             attributesList.add(new MpReachNlri(flowSpec, Constants.AFI_FLOWSPEC_VALUE, sAfi));
@@ -247,38 +238,14 @@
     }
 
     @Override
-    public void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
+    public void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
+                                     BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity) {
         Preconditions.checkNotNull(operType, "flow specification operation type cannot be null");
-        Preconditions.checkNotNull(prefix, "flow specification prefix cannot be null");
+        Preconditions.checkNotNull(routeKey, "flow specification prefix cannot be null");
         Preconditions.checkNotNull(flowSpec, "flow specification details cannot be null");
         Preconditions.checkNotNull(flowSpec.fsActionTlv(), "flow specification action cannot be null");
 
-        if (operType == FlowSpecOperation.ADD) {
-            if (flowSpec.routeDistinguisher() == null) {
-                if (flowSpecRibOut.flowSpecTree().containsKey(prefix)) {
-                    sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE,
-                                                    flowSpecRibOut.flowSpecTree().get(prefix));
-                }
-                flowSpecRibOut.add(prefix, flowSpec);
-            } else {
-                if (flowSpecRibOut.vpnFlowSpecTree().containsKey(flowSpec.routeDistinguisher())) {
-                    Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree;
-                    fsTree = flowSpecRibOut.vpnFlowSpecTree().get(flowSpec.routeDistinguisher());
-                    if (fsTree.containsKey(prefix)) {
-                        sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE,
-                                                        fsTree.get(prefix));
-                    }
-                }
-                flowSpecRibOut.add(flowSpec.routeDistinguisher(), prefix, flowSpec);
-            }
-        } else if (operType == FlowSpecOperation.DELETE) {
-            if (flowSpec.routeDistinguisher() == null) {
-                flowSpecRibOut.delete(prefix);
-            } else {
-                flowSpecRibOut.delete(flowSpec.routeDistinguisher(), prefix);
-            }
-        }
-        sendFlowSpecUpdateMessageToPeer(operType, flowSpec);
+        sendFlowSpecUpdateMessageToPeer(operType, routeKey, flowSpec, wideCommunity);
     }
 
     @Override
@@ -297,65 +264,6 @@
         }
     }
 
-    @Override
-    public void buildFlowSpecRib(List<BgpValueType> pathAttr) throws BgpParseException {
-        ListIterator<BgpValueType> iterator = pathAttr.listIterator();
-        BgpFlowSpecDetails bgpFlowSpecDetails = new BgpFlowSpecDetails();
-        FlowSpecOperation operType = FlowSpecOperation.UPDATE;
-
-        while (iterator.hasNext()) {
-            BgpValueType attr = iterator.next();
-            if (attr instanceof MpReachNlri) {
-                MpReachNlri mpReach = (MpReachNlri) attr;
-                bgpFlowSpecDetails.setFlowSpecComponents(mpReach.bgpFlowSpecInfo().flowSpecComponents());
-                bgpFlowSpecDetails.setRouteDistinguiher(mpReach.bgpFlowSpecInfo().routeDistinguisher());
-                operType = FlowSpecOperation.ADD;
-            }
-
-            if (attr instanceof BgpExtendedCommunity) {
-                BgpExtendedCommunity extCommunity = (BgpExtendedCommunity) attr;
-                bgpFlowSpecDetails.setFsActionTlv(extCommunity.fsActionTlv());
-            }
-
-            if (attr instanceof MpUnReachNlri) {
-                MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
-                bgpFlowSpecDetails.setFlowSpecComponents(mpUnReach.bgpFlowSpecInfo().flowSpecComponents());
-                bgpFlowSpecDetails.setRouteDistinguiher(mpUnReach.bgpFlowSpecInfo().routeDistinguisher());
-                operType = FlowSpecOperation.DELETE;
-            }
-        }
-
-        iterator = bgpFlowSpecDetails.flowSpecComponents().listIterator();
-        IpPrefix destIpPrefix = null;
-        IpPrefix srcIpPrefix = null;
-         while (iterator.hasNext()) {
-            BgpValueType fsAttr = iterator.next();
-            if (fsAttr instanceof BgpFsDestinationPrefix) {
-                BgpFsDestinationPrefix destinationPrefix = (BgpFsDestinationPrefix) fsAttr;
-                destIpPrefix = destinationPrefix.ipPrefix();
-            }
-
-            if (fsAttr instanceof BgpFsSourcePrefix) {
-                BgpFsSourcePrefix sourcePrefix = (BgpFsSourcePrefix) fsAttr;
-                srcIpPrefix = sourcePrefix.ipPrefix();
-            }
-        }
-        BgpFlowSpecPrefix prefix = new BgpFlowSpecPrefix(destIpPrefix, srcIpPrefix);
-        if (operType == FlowSpecOperation.ADD) {
-            if (bgpFlowSpecDetails.routeDistinguisher() == null) {
-                flowSpecRibIn.add(prefix, bgpFlowSpecDetails);
-            } else {
-                flowSpecRibIn.add(bgpFlowSpecDetails.routeDistinguisher(), prefix, bgpFlowSpecDetails);
-            }
-        } else if (operType == FlowSpecOperation.DELETE) {
-            if (bgpFlowSpecDetails.routeDistinguisher() == null) {
-                flowSpecRibIn.delete(prefix);
-            } else {
-                flowSpecRibIn.delete(bgpFlowSpecDetails.routeDistinguisher(), prefix);
-            }
-        }
-    }
-
     /**
      * Updates NLRI identifier node in a tree separately based on afi and safi.
      *
@@ -490,46 +398,12 @@
         localRibVpn.localRibUpdate(vpnAdjacencyRib());
     }
 
-    /**
-     * Update peer flow specification RIB on peer disconnect.
-     */
-    public void updateFlowSpecOnPeerDisconnect() {
-
-        boolean isCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
-                                                        Constants.AFI_FLOWSPEC_VALUE,
-                                                        Constants.SAFI_FLOWSPEC_VALUE);
-        if (isCapabilitySet) {
-            Set<BgpFlowSpecPrefix> flowSpecKeys = flowSpecRibOut.flowSpecTree().keySet();
-            for (BgpFlowSpecPrefix key : flowSpecKeys) {
-                BgpFlowSpecDetails flowSpecDetails = flowSpecRibOut.flowSpecTree().get(key);
-                sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE, flowSpecDetails);
-            }
-        }
-
-        boolean isVpnCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
-                                                        Constants.AFI_FLOWSPEC_VALUE,
-                                                        Constants.VPN_SAFI_FLOWSPEC_VALUE);
-        if (isVpnCapabilitySet) {
-            Set<RouteDistinguisher> flowSpecKeys = flowSpecRibOut.vpnFlowSpecTree().keySet();
-            for (RouteDistinguisher key : flowSpecKeys) {
-                Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree = flowSpecRibOut.vpnFlowSpecTree().get(key);
-
-                Set<BgpFlowSpecPrefix> fsKeys = fsTree.keySet();
-                for (BgpFlowSpecPrefix fsKey : fsKeys) {
-                    BgpFlowSpecDetails flowSpecDetails = flowSpecRibOut.flowSpecTree().get(fsKey);
-                    sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE, flowSpecDetails);
-                }
-            }
-        }
-    }
-
     // ************************
     // Channel related
     // ************************
 
     @Override
     public final void disconnectPeer() {
-        this.updateFlowSpecOnPeerDisconnect();
         this.channel.close();
     }
 
diff --git a/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpFlowSpecRibTest.java b/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpFlowSpecRibTest.java
deleted file mode 100644
index 8998dbe..0000000
--- a/protocols/bgp/ctl/src/test/java/org/onosproject/controller/impl/BgpFlowSpecRibTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.controller.impl;
-
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.bgp.controller.impl.BgpFlowSpecRib;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
-import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
-import org.onosproject.bgpio.types.BgpFsOperatorValue;
-import org.onosproject.bgpio.types.BgpFsPortNum;
-import org.onosproject.bgpio.types.BgpValueType;
-import org.onosproject.bgpio.types.RouteDistinguisher;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-
-/**
- * Test cases for BGP Selection Algorithm.
- */
-public class BgpFlowSpecRibTest {
-
-    /**
-     * Add flow specification to rib.
-     */
-    @Test
-    public void bgpFlowSpecRibTests1() {
-        List<BgpValueType> flowSpecComponents = new LinkedList<>();
-        List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
-        BgpFlowSpecRib rib = new BgpFlowSpecRib();
-
-        IpPrefix destinationPrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.1"), 32);
-        IpPrefix sourcePrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.2"), 32);
-
-        BgpFlowSpecPrefix prefix  = new BgpFlowSpecPrefix(destinationPrefix, sourcePrefix);
-
-        byte[] port = new byte[] {(byte) 0x1 };
-        operatorValue.add(new BgpFsOperatorValue((byte) 0x81, port));
-
-        BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
-        flowSpecComponents.add(portNum);
-
-        BgpFlowSpecDetails flowSpec = new BgpFlowSpecDetails(flowSpecComponents);
-
-        rib.add(prefix, flowSpec);
-
-        boolean isPresent = rib.flowSpecTree().containsKey(prefix);
-        assertThat(isPresent, is(true));
-    }
-
-    /**
-     * Add and delete flow specification to rib.
-     */
-    @Test
-    public void bgpFlowSpecRibTest2() {
-        List<BgpValueType> flowSpecComponents = new LinkedList<>();
-        List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
-        BgpFlowSpecRib rib = new BgpFlowSpecRib();
-
-        IpPrefix destinationPrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.1"), 32);
-        IpPrefix sourcePrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.2"), 32);
-
-        BgpFlowSpecPrefix prefix  = new BgpFlowSpecPrefix(destinationPrefix, sourcePrefix);
-        byte[] port = new byte[] {(byte) 0x1 };
-        operatorValue.add(new BgpFsOperatorValue((byte) 0x81, port));
-
-        BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
-        flowSpecComponents.add(portNum);
-
-        BgpFlowSpecDetails flowSpec = new BgpFlowSpecDetails(flowSpecComponents);
-
-        rib.add(prefix, flowSpec);
-
-        boolean isPresent = rib.flowSpecTree().containsKey(prefix);
-        assertThat(isPresent, is(true));
-
-        rib.delete(prefix);
-        isPresent = rib.flowSpecTree().containsKey(prefix);
-        assertThat(isPresent, is(false));
-
-    }
-
-    /**
-     * Add and delete flow specification with a specific VPN to rib.
-     */
-    @Test
-    public void bgpFlowSpecRibTest3() {
-        List<BgpValueType> flowSpecComponents = new LinkedList<>();
-        List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
-        RouteDistinguisher routeDistinguisher = new RouteDistinguisher(1);
-        BgpFlowSpecRib rib = new BgpFlowSpecRib();
-
-        IpPrefix destinationPrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.1"), 32);
-        IpPrefix sourcePrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.2"), 32);
-
-        BgpFlowSpecPrefix prefix  = new BgpFlowSpecPrefix(destinationPrefix, sourcePrefix);
-
-        byte[] port = new byte[] {(byte) 0x1 };
-        operatorValue.add(new BgpFsOperatorValue((byte) 0x81, port));
-
-        BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
-        flowSpecComponents.add(portNum);
-
-        BgpFlowSpecDetails flowSpec = new BgpFlowSpecDetails(flowSpecComponents);
-
-        rib.add(routeDistinguisher, prefix, flowSpec);
-
-        boolean isPresent = rib.vpnFlowSpecTree().containsKey(routeDistinguisher);
-        assertThat(isPresent, is(true));
-
-        rib.delete(routeDistinguisher, prefix);
-        isPresent = rib.vpnFlowSpecTree().containsKey(routeDistinguisher);
-        assertThat(isPresent, is(false));
-    }
-}