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

Change-Id: I2dfd6b88c4ae14a02d258a2cdc9ee35b9ff08292
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;