[ONOS-3857] BGP flow specification components encode and decode test.

Change-Id: I2830cd4d26ca044332a16845643ea99e11381209
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 49fc6a7..89f2f3d 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
@@ -189,73 +189,76 @@
                                                && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
                                                || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
                 List<BgpValueType> flowSpecComponents = new LinkedList<>();
-                BgpValueType flowSpecComponent = null;
 
-                byte nextHopLen = tempCb.readByte();
-                if (nextHopLen > 0) {
-                    InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
-                    if (ipAddress.isMulticastAddress()) {
-                        throw new BgpParseException("Multicast not supported");
-                    }
-                    ipNextHop = Ip4Address.valueOf(ipAddress);
-                }
+                if (tempCb.readableBytes() > 0) {
+                    BgpValueType flowSpecComponent = null;
 
-                byte reserved = tempCb.readByte();
-                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;
+                    byte nextHopLen = tempCb.readByte();
+                    if (nextHopLen > 0) {
+                        InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
+                        if (ipAddress.isMulticastAddress()) {
+                            throw new BgpParseException("Multicast not supported");
+                        }
+                        ipNextHop = Ip4Address.valueOf(ipAddress);
                     }
-                    flowSpecComponents.add(flowSpecComponent);
+
+                    byte reserved = tempCb.readByte();
+                    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;
+                        }
+                        flowSpecComponents.add(flowSpecComponent);
+                    }
                 }
                 return new MpReachNlri(new BgpFlowSpecDetails(flowSpecComponents), afi, safi);
             } else {
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 0931773..076d8dd 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
@@ -154,63 +154,65 @@
                                                && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
                                                || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
                 List<BgpValueType> flowSpecComponents = new LinkedList<>();
-                BgpValueType flowSpecComponent = null;
 
-                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;
+                if (tempCb.readableBytes() > 0) {
+                    BgpValueType flowSpecComponent = null;
+                    short totNlriLen = tempCb.getByte(tempCb.readerIndex());
+                    if (totNlriLen >= FLOW_SPEC_LEN) {
+                        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 = 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;
+                        }
+                        flowSpecComponents.add(flowSpecComponent);
+                    }
                 }
                 return new MpUnReachNlri(new BgpFlowSpecDetails(flowSpecComponents), afi, safi);
             } else {
diff --git a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MpReachNlriTest.java b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MpReachNlriTest.java
new file mode 100644
index 0000000..2b90b91
--- /dev/null
+++ b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MpReachNlriTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 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.types;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.core.Is.is;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpFactories;
+import org.onosproject.bgpio.protocol.BgpMessage;
+import org.onosproject.bgpio.protocol.BgpMessageReader;
+import org.onosproject.bgpio.protocol.ver4.BgpUpdateMsgVer4;
+
+/**
+ * Test for MP reach NLRI encoding and decoding.
+ */
+public class MpReachNlriTest {
+
+    /**
+     * This testcase checks BGP update message.
+     */
+    @Test
+    public void mpReachNlriTest1() throws BgpParseException {
+
+        // BGP flow spec  Message
+        byte[] flowSpecMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x00,
+                0x33, 0x40, 0x01, 0x01, 0x00, 0x40, 0x02, 0x04,
+                0x02, 0x01, 0x00, 0x64, (byte) 0x80, 0x04, 0x04, 0x00,
+                0x00, 0x00, 0x00, (byte) 0xc0, 0x10, 0x08, (byte) 0x80, 0x06,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x90, 0x0e,
+                0x00, 0x12, 0x00, 0x01, (byte) 0x85, 0x00, 0x00, 0x0c,
+                0x02, 0x20, (byte) 0xc0, (byte) 0xa8, 0x07, 0x36, 0x03, (byte) 0x81,
+                0x67, 0x04, (byte) 0x81, 0x01};
+
+        byte[] testFsMsg;
+        ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
+        buffer.writeBytes(flowSpecMsg);
+
+        BgpMessageReader<BgpMessage> reader = BgpFactories.getGenericReader();
+        BgpMessage message;
+        BgpHeader bgpHeader = new BgpHeader();
+
+        message = reader.readFrom(buffer, bgpHeader);
+
+        assertThat(message, instanceOf(BgpUpdateMsgVer4.class));
+        ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
+        message.writeTo(buf);
+
+        int readLen = buf.writerIndex();
+        testFsMsg = new byte[readLen];
+        buf.readBytes(testFsMsg, 0, readLen);
+
+        assertThat(testFsMsg, is(flowSpecMsg));
+    }
+}
diff --git a/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MpUnReachNlriTest.java b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MpUnReachNlriTest.java
new file mode 100644
index 0000000..afd1896
--- /dev/null
+++ b/protocols/bgp/bgpio/src/test/java/org/onosproject/bgpio/types/MpUnReachNlriTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 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.types;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.core.Is.is;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpFactories;
+import org.onosproject.bgpio.protocol.BgpMessage;
+import org.onosproject.bgpio.protocol.BgpMessageReader;
+import org.onosproject.bgpio.protocol.ver4.BgpUpdateMsgVer4;
+
+/**
+ * Test for MP unreach NLRI encoding and decoding.
+ */
+public class MpUnReachNlriTest {
+
+    /**
+     * This testcase checks BGP update message.
+     */
+    @Test
+    public void mpUnReachNlriTest() throws BgpParseException {
+
+        // BGP flow spec  Message
+        byte[] flowSpecMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                (byte) 0xff, 0x00, 0x2b, 0x02, 0x00, 0x00, 0x00, 0x14,
+                (byte) 0x90, 0x0f, 0x00, 0x10, 0x00, 0x01, (byte) 0x85,
+                0x0c, 0x02, 0x20, (byte) 0xc0, (byte) 0xa8, 0x07, 0x36,
+                0x03, (byte) 0x81, 0x67, 0x04, (byte) 0x81, 0x01};
+
+        byte[] testFsMsg;
+        ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
+        buffer.writeBytes(flowSpecMsg);
+
+        BgpMessageReader<BgpMessage> reader = BgpFactories.getGenericReader();
+        BgpMessage message;
+        BgpHeader bgpHeader = new BgpHeader();
+
+        message = reader.readFrom(buffer, bgpHeader);
+
+        assertThat(message, instanceOf(BgpUpdateMsgVer4.class));
+        ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
+        message.writeTo(buf);
+
+        int readLen = buf.writerIndex();
+        testFsMsg = new byte[readLen];
+        buf.readBytes(testFsMsg, 0, readLen);
+
+        assertThat(testFsMsg, is(flowSpecMsg));
+    }
+}
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 efd84fb..ce7a33c 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
@@ -43,6 +43,7 @@
 import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
 import org.onosproject.bgpio.types.AsPath;
 import org.onosproject.bgpio.types.As4Path;
+import org.onosproject.bgpio.types.BgpExtendedCommunity;
 import org.onosproject.bgpio.types.BgpValueType;
 import org.onosproject.bgpio.types.LocalPref;
 import org.onosproject.bgpio.types.Med;
@@ -227,7 +228,7 @@
             attributesList.add(new LocalPref(100));
         }
 
-        // TODO: Update flow spec action
+        attributesList.add(new BgpExtendedCommunity(flowSpec.fsActionTlv()));
 
         if (operType == FlowSpecOperation.ADD) {
             attributesList.add(new MpReachNlri(flowSpec, Constants.AFI_FLOWSPEC_VALUE, sAfi));