[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();
+ }
+}