[ONOS-4240, ONOS-4241] Support wide community optional path attribute

Change-Id: I59f9c4b69e8c26702ab955d58655497a394b9ec9
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityAttrHeader.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityAttrHeader.java
new file mode 100644
index 0000000..47e1014
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityAttrHeader.java
@@ -0,0 +1,210 @@
+/*
+ * 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.types;
+
+import com.google.common.base.MoreObjects;
+
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import java.util.Objects;
+
+/**
+ * Provides implementation of BGP wide community attribute header.
+ */
+public class WideCommunityAttrHeader implements BgpValueType {
+
+ /* 0                   1                   2                   3
+      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |             Type              |     Flags     |   Hop Count   |
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |            Length             |
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+
+    /*FLAG
+      +------+-------+----------------------------------------------------+
+      | Bit  | Value | Meaning                                            |
+      +------+-------+----------------------------------------------------+
+      |  0   |   0   | Local community value.                             |
+      |      |   1   | Registered community value.                        |
+      |  1   |   0   | Do not decrement Hop Count field across            |
+      |      |       | confederation boundaries.                          |
+      |      |   1   | Decrement Hop Count field across confederation     |
+      |      |       | boundaries.                                        |
+      | 2..7 |   -   | MUST be zero when sent and ignored upon receipt.   |
+      +------+-------+----------------------------------------------------+*/
+
+    public static final short TYPE = 1;
+    public static final short HEADER_LENGTH = 6;
+    private byte flag;
+    private byte hopCount;
+    private short length;
+
+    /**
+     * Wide community attribute header.
+     *
+     * @param flag to apply to all wide community container types
+     * @param hopCount represents the forwarding radius, in units of AS hops, for the given Wide BGP Community
+     * @param length field represents the total length of a given container
+     */
+    public WideCommunityAttrHeader(byte flag, byte hopCount, short length) {
+        this.flag = flag;
+        this.hopCount = hopCount;
+        this.length = length;
+    }
+
+    /**
+     * Returns object of this class with specified values.
+     *
+     * @param flag flag to apply to all wide community container types
+     * @param hopCount represents the forwarding radius, in units of AS hops, for the given Wide BGP Community
+     * @param length field represents the total length of a given container
+     * @return wide community attribute header
+     */
+    public static WideCommunityAttrHeader of(byte flag, byte hopCount, short length) {
+        return new WideCommunityAttrHeader(flag, hopCount, length);
+    }
+
+    /**
+     * Returns wide community flag.
+     *
+     * @return wide community flag
+     */
+    public byte flag() {
+        return flag;
+    }
+
+    /**
+     * Sets wide community flag.
+     *
+     * @param flag to apply to all wide community container types
+     */
+    public void setFlag(byte flag) {
+        this.flag = flag;
+    }
+
+    /**
+     * Returns hop count for wide community attribute.
+     *
+     * @return hop count from wide community
+     */
+    public byte hopCount() {
+        return hopCount;
+    }
+
+    /**
+     * Sets wide community hop count.
+     *
+     * @param hopCount represents the forwarding radius, in units of AS hops, for the given Wide BGP Community
+     */
+    public void setHopCount(byte hopCount) {
+        this.hopCount = hopCount;
+    }
+
+    /**
+     * Returns length of wide community attribute.
+     *
+     * @return length of wide community attribute
+     */
+    public short length() {
+        return length;
+    }
+
+    /**
+     * Sets wide community length.
+     *
+     * @param length total length of a given container
+     */
+    public void setLength(short length) {
+        this.length = length;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(flag, hopCount, length);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof WideCommunityAttrHeader) {
+            WideCommunityAttrHeader other = (WideCommunityAttrHeader) obj;
+            return Objects.equals(flag, other.flag) && Objects.equals(hopCount, other.hopCount)
+                    && Objects.equals(length, other.length);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iLenStartIndex = c.writerIndex();
+        c.writeShort(TYPE);
+        c.writeByte(flag);
+        c.writeByte(hopCount);
+        c.writeShort(length);
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the channel buffer and returns object of WideCommunityAttrHeader.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityAttrHeader
+     */
+    public static WideCommunityAttrHeader read(ChannelBuffer c) throws BgpParseException {
+
+        if (c.readableBytes() < HEADER_LENGTH) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                   BgpErrorType.ATTRIBUTE_LENGTH_ERROR, c.readableBytes());
+        }
+
+        short type = c.readShort();
+        byte flag = c.readByte();
+        byte hopCount = c.readByte();
+        short length = c.readShort();
+        return WideCommunityAttrHeader.of(flag, hopCount, length);
+    }
+
+    @Override
+    public short getType() {
+        return TYPE;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("Type", TYPE)
+                .add("flag", flag)
+                .add("hopCount", hopCount)
+                .add("length", length)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityExcludeTarget.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityExcludeTarget.java
new file mode 100644
index 0000000..819ffb6
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityExcludeTarget.java
@@ -0,0 +1,132 @@
+/*
+ * 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.types;
+
+import com.google.common.base.MoreObjects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.types.attr.WideCommunity;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides implementation of BGP wide community exclude target.
+ */
+public class WideCommunityExcludeTarget implements BgpValueType {
+
+    public static final byte TYPE = 2;
+    private List<BgpValueType> excludeTargetTlv;
+
+    /**
+     * Wide community targets.
+     *
+     * @param excludeTargetTlv wide community exclude target
+     */
+    public WideCommunityExcludeTarget(List<BgpValueType> excludeTargetTlv) {
+        this.excludeTargetTlv = excludeTargetTlv;
+    }
+
+    /**
+     * Returns object of this class with specified values.
+     *
+     * @param excludeTargetTlv exclude target
+     * @return object of WideCommunityExcludeTarget
+     */
+    public static BgpValueType of(List<BgpValueType> excludeTargetTlv) {
+        return new WideCommunityExcludeTarget(excludeTargetTlv);
+    }
+
+    /**
+     * Returns wide community targets.
+     *
+     * @return wide community targets
+     */
+    public List<BgpValueType> excludeTargetTlv() {
+        return excludeTargetTlv;
+    }
+
+    /**
+     * Sets wide community target.
+     *
+     * @param excludeTargetTlv wide community  exclude targets
+     */
+    public void setExcludeTargetTlv(List<BgpValueType> excludeTargetTlv) {
+        this.excludeTargetTlv = excludeTargetTlv;
+    }
+
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(excludeTargetTlv);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof WideCommunityExcludeTarget) {
+            WideCommunityExcludeTarget other = (WideCommunityExcludeTarget) obj;
+            return Objects.equals(excludeTargetTlv, other.excludeTargetTlv);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iLenStartIndex = c.writerIndex();
+        WideCommunity.encodeWideCommunityTlv(c, excludeTargetTlv());
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the channel buffer and returns object of WideCommunityExcludeTarget.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityExcludeTarget
+     * @throws BgpParseException on read error
+     */
+    public static WideCommunityExcludeTarget read(ChannelBuffer c) throws BgpParseException {
+        return new WideCommunityExcludeTarget(WideCommunity.decodeWideCommunityTlv(c));
+    }
+
+    @Override
+    public short getType() {
+        return TYPE;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .omitNullValues()
+                .add("Type", TYPE)
+                .add("targetTlv", excludeTargetTlv)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityInteger.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityInteger.java
new file mode 100644
index 0000000..88bb2c4
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityInteger.java
@@ -0,0 +1,175 @@
+/*
+ * 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.types;
+
+import com.google.common.base.MoreObjects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.util.Validation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides implementation of BGP wide community integer subtlv.
+ */
+public class WideCommunityInteger implements BgpValueType {
+    public static final short TYPE = 4;
+    private List<Integer> integer;
+
+    /**
+     * Creates an instance of wide community integer subtlv.
+     *
+     * @param integer integer
+     */
+    public WideCommunityInteger(List<Integer> integer) {
+        this.integer = integer;
+    }
+
+    /**
+     * Returns object of this class with specified values.
+     *
+     * @param integer wide community subtlv integer
+     * @return object of WideCommunityInteger
+     */
+    public static WideCommunityInteger of(List<Integer> integer) {
+        return new WideCommunityInteger(integer);
+    }
+
+    /**
+     * Returns wide community subtlv integer.
+     *
+     * @return wide community subtlv integer
+     */
+    public List<Integer> integer() {
+        return integer;
+    }
+
+    /**
+     * Sets wide community subtlv integer.
+     *
+     * @param integer wide community subtlv integer
+     */
+    public void setInteger(List<Integer> integer) {
+        this.integer = integer;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(integer);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof WideCommunityInteger) {
+            WideCommunityInteger other = (WideCommunityInteger) obj;
+            return Objects.equals(integer, other.integer);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iLenStartIndex = c.writerIndex();
+
+        Iterator<Integer> listIterator = integer.iterator();
+        c.writeByte(TYPE);
+
+        int iLengthIndex = c.writerIndex();
+        c.writeShort(0);
+
+        while (listIterator.hasNext()) {
+            Integer integer = listIterator.next();
+            if (integer instanceof Integer) {
+                c.writeInt(integer);
+            }
+        }
+
+        int length = c.writerIndex() - iLengthIndex;
+        c.setShort(iLengthIndex, (short) (length - 2));
+
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the channel buffer and returns object of WideCommunityInteger.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityInteger
+     * @throws BgpParseException on read error
+     */
+    public static WideCommunityInteger read(ChannelBuffer c) throws BgpParseException {
+
+        List<Integer> integer = new ArrayList<>();
+        short length;
+
+        if (c.readableBytes() < 2) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                   c.readableBytes());
+        }
+
+        length = c.readShort();
+        if (length == 0) {
+            return new WideCommunityInteger(integer);
+        }
+
+        if (c.readableBytes() < length) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                   c.readableBytes());
+        }
+
+        while (c.readableBytes() > 0) {
+            if (c.readableBytes() < 4) {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                       c.readableBytes());
+            }
+            integer.add(c.readInt());
+        }
+
+        return new WideCommunityInteger(integer);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .omitNullValues()
+                .add("integer", integer)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public short getType() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityIpV4Neighbour.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityIpV4Neighbour.java
new file mode 100644
index 0000000..92464f4
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityIpV4Neighbour.java
@@ -0,0 +1,208 @@
+/*
+ * 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.types;
+
+import com.google.common.base.MoreObjects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onlab.packet.IpAddress;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.util.Validation;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides implementation of BGP wide community IPV4 neighbour subtlv.
+ */
+public class WideCommunityIpV4Neighbour implements BgpValueType {
+    public static final byte TYPE = 8;
+    private List<IpV4Neighbour> ipv4Neighbour;
+    public static final byte IPV4_NEIGHBOUR_SIZE = 8;
+
+    /**
+     * Creates an instance of wide community ipv4 neighbour subtlv.
+     *
+     */
+    public WideCommunityIpV4Neighbour() {
+        this.ipv4Neighbour = new ArrayList<>();
+    }
+
+    /**
+     * Adds local and remote speakers.
+     *
+     * @param localSpeaker local speaker
+     * @param remoteSpeaker remote speaker
+     */
+    public void add(IpAddress localSpeaker, IpAddress remoteSpeaker) {
+        ipv4Neighbour.add(new IpV4Neighbour(localSpeaker, remoteSpeaker));
+    }
+
+    /**
+     * Deletes local and remote speakers.
+     *
+     * @param localSpeaker local speaker
+     * @param remoteSpeaker remote speaker
+     */
+    public void remove(IpAddress localSpeaker, IpAddress remoteSpeaker) {
+        ipv4Neighbour.remove(new IpV4Neighbour(localSpeaker, remoteSpeaker));
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ipv4Neighbour);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof WideCommunityIpV4Neighbour) {
+            WideCommunityIpV4Neighbour other = (WideCommunityIpV4Neighbour) obj;
+            return Objects.equals(ipv4Neighbour, other.ipv4Neighbour);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iLenStartIndex = c.writerIndex();
+
+        Iterator<IpV4Neighbour> listIterator = ipv4Neighbour.iterator();
+        c.writeByte(TYPE);
+
+        int iLengthIndex = c.writerIndex();
+        c.writeShort(0);
+
+        while (listIterator.hasNext()) {
+            IpV4Neighbour speaker = listIterator.next();
+            if (speaker instanceof IpV4Neighbour) {
+                c.writeInt(Integer.valueOf(speaker.localSpeaker.toString()));
+                c.writeInt(Integer.valueOf(speaker.remoteSpeaker.toString()));
+            }
+        }
+
+        int length = c.writerIndex() - iLengthIndex;
+        c.setShort(iLengthIndex, (short) (length - 2));
+
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the channel buffer and returns object of WideCommunityIpV4Neighbour.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityIpV4Neighbour
+     * @throws BgpParseException on read error
+     */
+    public static WideCommunityIpV4Neighbour read(ChannelBuffer c) throws BgpParseException {
+        WideCommunityIpV4Neighbour wideCommNeighbour = new WideCommunityIpV4Neighbour();
+        short length;
+
+        if (c.readableBytes() == 0) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                   c.readableBytes());
+        }
+
+        length = c.readShort();
+        if (c.readableBytes() == 0) {
+            return wideCommNeighbour;
+        }
+
+        if (c.readableBytes() < length) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                   c.readableBytes());
+        }
+
+        while (c.readableBytes() > 0) {
+            if (c.readableBytes() < IPV4_NEIGHBOUR_SIZE) {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                       c.readableBytes());
+            }
+
+            IpAddress localSpeaker = IpAddress.valueOf(c.readInt());
+            IpAddress remoteSpeaker = IpAddress.valueOf(c.readInt());
+
+            wideCommNeighbour.add(localSpeaker, remoteSpeaker);
+
+        }
+
+        return wideCommNeighbour;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("ipv4Neighbour", ipv4Neighbour)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public short getType() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    /*
+     * IpV4Neighbour class contain remote and local speaker.
+     */
+    private class IpV4Neighbour {
+        private IpAddress localSpeaker;
+        private IpAddress remoteSpeaker;
+
+        /**
+         * Creates an instance of ipv4 neighbour.
+         *
+         * @param localSpeaker ip address of local speaker
+         * @param remoteSpeaker  ip address of remote speaker
+         */
+        public IpV4Neighbour(IpAddress localSpeaker, IpAddress remoteSpeaker) {
+            this.localSpeaker = localSpeaker;
+            this.remoteSpeaker = remoteSpeaker;
+        }
+
+        /**
+         * Returns IPV4 neighbour local speaker.
+         *
+         * @return IPV4 neighbour local speaker
+         */
+        public IpAddress localSpeaker() {
+            return localSpeaker;
+        }
+
+        /**
+         * Returns IPV4 neighbour remote speaker.
+         *
+         * @return IPV4 neighbour remote speaker
+         */
+        public IpAddress remoteSpeaker() {
+            return remoteSpeaker;
+        }
+    }
+}
\ No newline at end of file
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityParameter.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityParameter.java
new file mode 100644
index 0000000..129bdb9
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityParameter.java
@@ -0,0 +1,131 @@
+/*
+ * 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.types;
+
+import com.google.common.base.MoreObjects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.types.attr.WideCommunity;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides implementation of BGP wide community parameter.
+ */
+public class WideCommunityParameter implements BgpValueType {
+
+    public static final byte TYPE = 3;
+    private List<BgpValueType> parameterTlv;
+
+    /**
+     * Creates an instance of wide community parameter.
+     *
+     * @param parameterTlv wide community parameter
+     */
+    public WideCommunityParameter(List<BgpValueType> parameterTlv) {
+        this.parameterTlv = parameterTlv;
+    }
+
+    /**
+     * Returns object of this class with specified values.
+     *
+     * @param parameterTlv wide community parameter
+     * @return object of WideCommunityParameter
+     */
+    public static WideCommunityParameter of(List<BgpValueType> parameterTlv) {
+        return new WideCommunityParameter(parameterTlv);
+    }
+
+    /**
+     * Returns wide community parameter.
+     *
+     * @return wide community parameter
+     */
+    public List<BgpValueType> parameterTlv() {
+        return parameterTlv;
+    }
+
+    /**
+     * Sets wide community parameter.
+     *
+     * @param parameterTlv wide community parameter
+     */
+    public void setParameterTlv(List<BgpValueType> parameterTlv) {
+        this.parameterTlv = parameterTlv;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(parameterTlv);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof WideCommunityParameter) {
+            WideCommunityParameter other = (WideCommunityParameter) obj;
+            return Objects.equals(parameterTlv, other.parameterTlv);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iLenStartIndex = c.writerIndex();
+        WideCommunity.encodeWideCommunityTlv(c, parameterTlv());
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the channel buffer and returns object of WideCommunityParameter.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityParameter
+     * @throws BgpParseException on read error
+     */
+    public static WideCommunityParameter read(ChannelBuffer c) throws BgpParseException {
+        return new WideCommunityParameter(WideCommunity.decodeWideCommunityTlv(c));
+    }
+
+    @Override
+    public short getType() {
+        return TYPE;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .omitNullValues()
+                .add("Type", TYPE)
+                .add("parameterTlv", parameterTlv)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityTarget.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityTarget.java
new file mode 100644
index 0000000..47553e3
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/WideCommunityTarget.java
@@ -0,0 +1,130 @@
+/*
+ * 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.types;
+
+import com.google.common.base.MoreObjects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.types.attr.WideCommunity;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides implementation of BGP wide community target.
+ */
+public class WideCommunityTarget implements BgpValueType {
+
+    public static final byte TYPE = 1;
+    private List<BgpValueType> targetTlv;
+
+    /**
+     * Creates an instance of Wide community targets.
+     *
+     * @param targetTlv wide community targets to match
+     */
+    public WideCommunityTarget(List<BgpValueType> targetTlv) {
+        this.targetTlv = targetTlv;
+    }
+
+    /**
+     * Returns object of this class with specified values.
+     *
+     * @param targetTlv wide community target
+     * @return object of WideCommunityTarget
+     */
+    public static WideCommunityTarget of(List<BgpValueType> targetTlv) {
+        return new WideCommunityTarget(targetTlv);
+    }
+
+    /**
+     * Returns wide community targets.
+     *
+     * @return wide community targets
+     */
+    public List<BgpValueType> targetTlv() {
+        return targetTlv;
+    }
+
+    /**
+     * Sets wide community target.
+     *
+     * @param targetTlv wide community targets to match
+     */
+    public void setTargetTlv(List<BgpValueType> targetTlv) {
+        this.targetTlv = targetTlv;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(targetTlv);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof WideCommunityTarget) {
+            WideCommunityTarget other = (WideCommunityTarget) obj;
+            return Objects.equals(targetTlv, other.targetTlv);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iLenStartIndex = c.writerIndex();
+        WideCommunity.encodeWideCommunityTlv(c, targetTlv());
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the channel buffer and returns object of WideCommunityTarget.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityTarget
+     * @throws BgpParseException on read error
+     */
+    public static WideCommunityTarget read(ChannelBuffer c) throws BgpParseException {
+        return new WideCommunityTarget(WideCommunity.decodeWideCommunityTlv(c));
+    }
+
+    @Override
+    public short getType() {
+        return TYPE;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("Type", TYPE)
+                .add("targetTlv", targetTlv)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/WideCommunity.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/WideCommunity.java
new file mode 100644
index 0000000..25afd95
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/WideCommunity.java
@@ -0,0 +1,454 @@
+/*
+ * 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.types.attr;
+
+import com.google.common.base.MoreObjects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onlab.packet.IpAddress;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.types.BgpErrorType;
+import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.WideCommunityAttrHeader;
+import org.onosproject.bgpio.types.WideCommunityExcludeTarget;
+import org.onosproject.bgpio.types.WideCommunityInteger;
+import org.onosproject.bgpio.types.WideCommunityIpV4Neighbour;
+import org.onosproject.bgpio.types.WideCommunityParameter;
+import org.onosproject.bgpio.types.WideCommunityTarget;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Provides implementation of wide community path attribute.
+ */
+public class WideCommunity implements BgpValueType {
+
+    private static final Logger log = LoggerFactory.getLogger(WideCommunity.class);
+    public static final byte TYPE = (byte) 254; /* TODO: IANA Assigned */
+    public static final short LENGTH = 4;
+    public static final byte TYPE_LENGTH_SIZE = 3;
+    public static final byte FLAGS = (byte) 0x40;
+    private WideCommunityAttrHeader wideCommunityHeader;
+    private int community;
+    private int localAsn;
+    private int contextAsn;
+    private WideCommunityTarget target;
+    private WideCommunityExcludeTarget excludeTarget;
+    private WideCommunityParameter parameter;
+
+    /**
+     * Creates an instance of wide community.
+     *
+     * @param wideCommunityHeader wide community header
+     * @param community wide community
+     * @param localAsn local ASN number
+     * @param contextAsn context ASN number
+     * @param target wide community include target
+     * @param excludeTarget wide community exclude target
+     * @param parameter wide community parameter
+     */
+    public WideCommunity(WideCommunityAttrHeader wideCommunityHeader, int community, int localAsn, int contextAsn,
+                             WideCommunityTarget target, WideCommunityExcludeTarget excludeTarget,
+                             WideCommunityParameter parameter) {
+        this.wideCommunityHeader = wideCommunityHeader;
+        this.community = community;
+        this.localAsn = localAsn;
+        this.contextAsn = contextAsn;
+        this.target = target;
+        this.excludeTarget = excludeTarget;
+        this.parameter = parameter;
+    }
+
+    /**
+     * Returns object of this class with specified values.
+     *
+     * @param community wide community
+     * @param localAsn local ASN number
+     * @param contextAsn context ASN number
+     * @param target wide community include target
+     * @param excludeTarget wide community exclude target
+     * @param parameter wide community parameter
+     * @return object of WideCommunityAttr
+     */
+    public static WideCommunity of(WideCommunityAttrHeader wideCommunityHeader, int community, int localAsn,
+                                       int contextAsn, WideCommunityTarget target,
+                                       WideCommunityExcludeTarget excludeTarget, WideCommunityParameter parameter) {
+        return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn, target, excludeTarget,
+                                     parameter);
+    }
+
+    /**
+     * Returns wide community value.
+     *
+     * @return wide community value
+     */
+    public int community() {
+        return community;
+    }
+
+    /**
+     * Sets wide community value.
+     *
+     * @param community wide community value
+     */
+    public void setCommunity(int community) {
+        this.community = community;
+    }
+
+    /**
+     * Returns wide community local autonomous number.
+     *
+     * @return local autonomous number
+     */
+    public int localAsn() {
+        return localAsn;
+    }
+
+    /**
+     * Sets wide community local autonomous number.
+     *
+     * @param localAsn local autonomous number
+     */
+    public void setLocalAsn(int localAsn) {
+        this.localAsn = localAsn;
+    }
+
+    /**
+     * Returns wide community context autonomous number.
+     *
+     * @return contest autonomous number
+     */
+    public int contextAsn() {
+        return contextAsn;
+    }
+
+    /**
+     * Sets wide community context autonomous number.
+     *
+     * @param contextAsn context autonomous number
+     */
+    public void setContextAsn(int contextAsn) {
+        this.contextAsn = contextAsn;
+    }
+
+    /**
+     * Returns wide community target.
+     *
+     * @return wide community target
+     */
+    public WideCommunityTarget target() {
+        return target;
+    }
+
+    /**
+     * Sets wide community target.
+     *
+     * @param target wide community target
+     */
+    public void setTarget(WideCommunityTarget target) {
+        this.target = target;
+    }
+
+    /**
+     * Returns wide community exclude target.
+     *
+     * @return wide community exclude target
+     */
+    public WideCommunityExcludeTarget excludeTarget() {
+        return excludeTarget;
+    }
+
+    /**
+     * Sets wide community exclude target.
+     *
+     * @param excludeTarget wide community texclude arget
+     */
+    public void setExcludeTarget(WideCommunityExcludeTarget excludeTarget) {
+        this.excludeTarget = excludeTarget;
+    }
+
+    /**
+     * Returns wide community parameter.
+     *
+     * @return wide community parameter
+     */
+    public WideCommunityParameter parameter() {
+        return parameter;
+    }
+
+    /**
+     * Sets wide community parameter.
+     *
+     * @param parameter wide community parameter
+     */
+    public void setParameter(WideCommunityParameter parameter) {
+        this.parameter = parameter;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(wideCommunityHeader, community, localAsn, contextAsn, target, excludeTarget, parameter);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof WideCommunity) {
+            WideCommunity other = (WideCommunity) obj;
+            return Objects.equals(wideCommunityHeader, other.wideCommunityHeader)
+                    && Objects.equals(community, other.community) && Objects.equals(localAsn, other.localAsn)
+                    && Objects.equals(contextAsn, other.contextAsn) && Objects.equals(target, other.target)
+                    && Objects.equals(excludeTarget, other.excludeTarget) && Objects.equals(parameter, other.parameter);
+        }
+        return false;
+    }
+
+    @Override
+    public int write(ChannelBuffer c) {
+        int iTargetLenIndex;
+        int length;
+        int iLenStartIndex = c.writerIndex();
+        c.writeByte(FLAGS); // TODO: update flag value
+        c.writeByte(TYPE);
+
+        int iLengthIndex = c.writerIndex();
+        c.writeShort(0);
+
+        wideCommunityHeader.write(c);
+
+        c.writeInt(community);
+        c.writeInt(localAsn);
+        c.writeInt(contextAsn);
+
+        if (target() != null) {
+            c.writeByte(WideCommunityTarget.TYPE);
+            iTargetLenIndex = c.writerIndex();
+            c.writeShort(0); // length
+
+            target.write(c);
+
+            length = c.writerIndex() - iTargetLenIndex;
+            c.setShort(iTargetLenIndex, (short) (length - 2));
+        }
+
+        if (excludeTarget() != null) {
+            c.writeByte(WideCommunityExcludeTarget.TYPE);
+            iTargetLenIndex = c.writerIndex();
+            c.writeShort(0); // length
+
+            excludeTarget.write(c);
+
+            length = c.writerIndex() - iTargetLenIndex;
+            c.setShort(iTargetLenIndex, (short) (length - 2));
+        }
+
+        if (parameter() != null) {
+            c.writeByte(WideCommunityParameter.TYPE);
+            iTargetLenIndex = c.writerIndex();
+            c.writeShort(0); // length
+
+            parameter.write(c);
+
+            length = c.writerIndex() - iTargetLenIndex;
+            c.setShort(iTargetLenIndex, (short) (length - 2));
+        }
+
+        length = c.writerIndex() - iLengthIndex;
+        c.setShort(iLengthIndex, (short) (length - 2));
+
+        return c.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Reads the wide community attribute.
+     *
+     * @param c ChannelBuffer
+     * @return object of WideCommunityAttr
+     * @throws BgpParseException while parsing BgpPrefixAttrRouteTag
+     */
+    public static WideCommunity read(ChannelBuffer c) throws BgpParseException {
+
+        WideCommunityAttrHeader wideCommunityHeader;
+        int community;
+        int localAsn;
+        int contextAsn;
+        WideCommunityTarget target = null;
+        WideCommunityExcludeTarget excludeTarget = null;
+        WideCommunityParameter parameter = null;
+
+        short length = c.readShort();
+
+        if (c.readableBytes() < length) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
+        }
+
+        wideCommunityHeader = WideCommunityAttrHeader.read(c);
+        if ((c.readableBytes() < 12) || (c.readableBytes() < wideCommunityHeader.length())) {
+            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
+        }
+
+        community = c.readInt();
+        localAsn = c.readInt();
+        contextAsn = c.readInt();
+
+        while (c.readableBytes() > 0) {
+
+            if (c.readableBytes() < TYPE_LENGTH_SIZE) {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                       c.readableBytes());
+            }
+
+            byte type = c.readByte();
+            length = c.readShort();
+
+            if (c.readableBytes() < length) {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                       c.readableBytes());
+            }
+
+            if (type == WideCommunityTarget.TYPE) {
+                target = WideCommunityTarget.read(c);
+            } else if (type == WideCommunityExcludeTarget.TYPE) {
+                excludeTarget = WideCommunityExcludeTarget.read(c);
+            } else if (type == WideCommunityParameter.TYPE) {
+                parameter = WideCommunityParameter.read(c);
+            }
+        }
+        return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn,
+                                     target, excludeTarget, parameter);
+    }
+
+    /**
+     * Encode wide community target(s).
+     *
+     * @param c channel buffer
+     * @param targetTlv wide community include/exclude target
+     */
+    public static void encodeWideCommunityTlv(ChannelBuffer c,
+                                    List<BgpValueType> targetTlv) {
+
+        /*
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         |  IPV4Neig(8)  |   Length:                   8 |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         | local                                               10101010  |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         | remote                                              10101010  |
+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+         * */
+        List<BgpValueType> target = targetTlv;
+        if (target == null) {
+           log.debug("target is null");
+           return;
+        }
+        Iterator<BgpValueType> listIterator = targetTlv.iterator();
+
+        while (listIterator.hasNext()) {
+            BgpValueType attr = listIterator.next();
+            if (attr instanceof WideCommunityIpV4Neighbour) {
+                WideCommunityIpV4Neighbour ipv4Neig = (WideCommunityIpV4Neighbour) attr;
+                ipv4Neig.write(c);
+            } else if (attr instanceof WideCommunityInteger) {
+                WideCommunityInteger integer = (WideCommunityInteger) attr;
+                integer.write(c);
+            }
+        }
+        return;
+    }
+
+    /**
+     * Decode wide community target(s).
+     *
+     * @param c channel buffer
+     * @return target list
+     * @throws BgpParseException on decode error
+     */
+    public static List<BgpValueType> decodeWideCommunityTlv(ChannelBuffer c) throws BgpParseException {
+        List<BgpValueType> targetTlv = new ArrayList<>();
+
+        while (c.readableBytes() > 0) {
+            if (c.readableBytes() < TYPE_LENGTH_SIZE) {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                       c.readableBytes());
+            }
+
+            byte atomType = c.readByte();
+            short atomLength = c.readShort();
+
+            if (c.readableBytes() < atomLength) {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
+                                       atomLength);
+            }
+
+            if (atomType == WideCommunityIpV4Neighbour.TYPE) {
+                ChannelBuffer tempBuf = c.readBytes(atomLength);
+
+                WideCommunityIpV4Neighbour wideCommAtom = new WideCommunityIpV4Neighbour();
+
+                while (tempBuf.readableBytes() > 0) {
+                    wideCommAtom.add(IpAddress.valueOf(tempBuf.readInt()),
+                                     IpAddress.valueOf(tempBuf.readInt()));
+                }
+                targetTlv.add(wideCommAtom);
+            } else if (atomType == WideCommunityInteger.TYPE) {
+                ChannelBuffer tempBuf = c.readBytes(atomLength);
+                List<Integer> integer = new ArrayList<>();
+                while (tempBuf.readableBytes() > 0) {
+                    integer.add(tempBuf.readInt());
+                }
+                targetTlv.add(new WideCommunityInteger(integer));
+            } else {
+                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
+                                       atomLength);
+            }
+        }
+        return targetTlv;
+    }
+
+    @Override
+    public short getType() {
+        return TYPE;
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        // TODO:
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .omitNullValues()
+                .add("FLAGS", FLAGS)
+                .add("wideCommunityHeader", wideCommunityHeader)
+                .add("community", community)
+                .add("localAsn", localAsn)
+                .add("contextAsn", contextAsn)
+                .add("target", target)
+                .add("excludeTarget", excludeTarget)
+                .add("parameter", parameter).toString();
+    }
+}