[Emu] [ONOS-2598] Implementation of BGP Capabilities parsing, decoding and encoding
Change-Id: I5893c490f97ad23a0180b847e8b8af9b00560806
diff --git a/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPOpenMsg.java b/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPOpenMsg.java
index c41e5eb..2271b60 100644
--- a/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPOpenMsg.java
+++ b/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPOpenMsg.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.onosproject.bgpio.protocol;
import java.util.LinkedList;
@@ -91,8 +90,7 @@
/**
* Sets hold time in Open Message and return its builder.
*
- * @param holdtime
- * hold timer value in open message
+ * @param holdtime hold timer value in open message
* @return builder by setting hold time
*/
Builder setHoldTime(short holdtime);
@@ -107,8 +105,7 @@
/**
* Sets AS number in Open Message and return its builder.
*
- * @param asNumber
- * as number in open message
+ * @param asNumber as number in open message
* @return builder by setting asNumber
*/
Builder setAsNumber(short asNumber);
@@ -123,8 +120,7 @@
/**
* Sets BGP Identifier in Open Message and return its builder.
*
- * @param bgpId
- * BGP Identifier in open message
+ * @param bgpId BGP Identifier in open message
* @return builder by setting BGP Identifier
*/
Builder setBgpId(int bgpId);
@@ -139,12 +135,29 @@
/**
* Sets capabilities in Open Message and return its builder.
*
- * @param capabilityTlv
- * capabilities in open message
+ * @param capabilityTlv capabilities in open message
* @return builder by setting capabilities
*/
Builder setCapabilityTlv(LinkedList<BGPValueType> capabilityTlv);
+ /**
+ * Sets isLargeAsCapabilityTlvSet and return its builder.
+ *
+ * @param isLargeAsCapabilitySet
+ * boolean value to know whether large AS capability is set or not
+ * @return builder by setting capabilities
+ */
+ Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet);
+
+ /**
+ * Sets isLsCapabilityTlvSet and return its builder.
+ *
+ * @param isLsCapabilitySet
+ * boolean value to know whether LS capability is set or not
+ * @return builder by setting capabilities
+ */
+ Builder setLsCapabilityTlv(boolean isLsCapabilitySet);
+
@Override
Builder setHeader(BGPHeader bgpMsgHeader);
}
diff --git a/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java b/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java
index 1348ecf..bd22889 100644
--- a/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java
+++ b/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.onosproject.bgpio.protocol.ver4;
import java.util.LinkedList;
@@ -29,6 +28,8 @@
import org.onosproject.bgpio.types.BGPErrorType;
import org.onosproject.bgpio.types.BGPHeader;
import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
+import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,8 +68,13 @@
public static final int MSG_HEADER_LENGTH = 19;
public static final int MARKER_LENGTH = 16;
public static final int DEFAULT_HOLD_TIME = 120;
+ public static final short AS_TRANS = 23456;
public static final int OPT_PARA_TYPE_CAPABILITY = 2;
public static final BGPType MSG_TYPE = BGPType.OPEN;
+ public static final short AFI = 16388;
+ public static final byte SAFI = 71;
+ public static final byte RES = 0;
+ public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65;
public static final byte[] MARKER = 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};
@@ -79,6 +85,7 @@
private short asNumber;
private short holdTime;
private int bgpId;
+ private boolean isLargeAsCapabilitySet;
private LinkedList<BGPValueType> capabilityTlv;
public static final BGPOpenMsgVer4.Reader READER = new Reader();
@@ -98,18 +105,12 @@
/**
* Constructor to initialize all variables of BGP Open message.
*
- * @param bgpMsgHeader
- * BGP Header in open message
- * @param version
- * BGP version in open message
- * @param holdTime
- * hold time in open message
- * @param asNumber
- * AS number in open message
- * @param bgpId
- * BGP identifier in open message
- * @param capabilityTlv
- * capabilities in open message
+ * @param bgpMsgHeader BGP Header in open message
+ * @param version BGP version in open message
+ * @param holdTime hold time in open message
+ * @param asNumber AS number in open message
+ * @param bgpId BGP identifier in open message
+ * @param capabilityTlv capabilities in open message
*/
public BGPOpenMsgVer4(BGPHeader bgpMsgHeader, byte version, short asNumber, short holdTime,
int bgpId, LinkedList<BGPValueType> capabilityTlv) {
@@ -236,7 +237,44 @@
LinkedList<BGPValueType> capabilityTlv = new LinkedList<>();
- // TODO: Capability parsing
+ while (cb.readableBytes() > 0) {
+ BGPValueType tlv;
+ short type = cb.readByte();
+ short length = cb.readByte();
+
+ switch (type) {
+ case FourOctetAsNumCapabilityTlv.TYPE:
+ log.debug("FourOctetAsNumCapabilityTlv");
+ if (FourOctetAsNumCapabilityTlv.LENGTH != length) {
+ throw new BGPParseException("Invalid length received for FourOctetAsNumCapabilityTlv.");
+ }
+ if (length > cb.readableBytes()) {
+ throw new BGPParseException("Four octet as num tlv length"
+ + " is more than readableBytes.");
+ }
+ int as4Num = cb.readInt();
+ tlv = new FourOctetAsNumCapabilityTlv(as4Num);
+ break;
+ case MultiProtocolExtnCapabilityTlv.TYPE:
+ log.debug("MultiProtocolExtnCapabilityTlv");
+ if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
+ throw new BGPParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
+ }
+ if (length > cb.readableBytes()) {
+ throw new BGPParseException("BGP LS tlv length is more than readableBytes.");
+ }
+ short afi = cb.readShort();
+ byte res = cb.readByte();
+ byte safi = cb.readByte();
+ tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
+ break;
+ default:
+ log.debug("Warning: Unsupported TLV: " + type);
+ cb.skipBytes(length);
+ continue;
+ }
+ capabilityTlv.add(tlv);
+ }
return capabilityTlv;
}
@@ -248,11 +286,13 @@
private boolean isHeaderSet = false;
private BGPHeader bgpMsgHeader;
private boolean isHoldTimeSet = false;
- private short holdTime;
+ private short holdTime;
private boolean isAsNumSet = false;
private short asNumber;
private boolean isBgpIdSet = false;
private int bgpId;
+ private boolean isLargeAsCapabilityTlvSet = false;
+ private boolean isLsCapabilityTlvSet = false;
LinkedList<BGPValueType> capabilityTlv = new LinkedList<>();
@@ -269,7 +309,18 @@
throw new BGPParseException("BGPID is not set (mandatory)");
}
- // TODO: capabilities build
+ if (this.isLargeAsCapabilityTlvSet) {
+ BGPValueType tlv;
+ int iValue = this.getAsNumber();
+ tlv = new FourOctetAsNumCapabilityTlv(iValue);
+ this.capabilityTlv.add(tlv);
+ }
+
+ if (this.isLsCapabilityTlvSet) {
+ BGPValueType tlv;
+ tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
+ this.capabilityTlv.add(tlv);
+ }
return new BGPOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId,
this.capabilityTlv);
@@ -342,6 +393,18 @@
this.capabilityTlv = capabilityTlv;
return this;
}
+
+ @Override
+ public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) {
+ this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet;
+ return this;
+ }
+
+ @Override
+ public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) {
+ this.isLsCapabilityTlvSet = isLsCapabilitySet;
+ return this;
+ }
}
@Override
@@ -364,6 +427,7 @@
public void write(ChannelBuffer cb, BGPOpenMsgVer4 message) throws BGPParseException {
int optParaLen = 0;
+ int as4num = 0;
int startIndex = cb.writerIndex();
@@ -377,8 +441,29 @@
// write version in 1-octet
cb.writeByte(message.version);
- // TODO : Write AS number based on capabilities
- cb.writeShort(message.asNumber);
+ // get as4num if LS Capability is set
+ if (message.isLargeAsCapabilitySet) {
+ LinkedList<BGPValueType> capabilityTlv = message
+ .getCapabilityTlv();
+ ListIterator<BGPValueType> listIterator = capabilityTlv
+ .listIterator();
+
+ while (listIterator.hasNext()) {
+ BGPValueType tlv = listIterator.next();
+ if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
+ as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
+ break;
+ }
+ }
+ }
+
+ if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) {
+ // write As number as AS_TRANS
+ cb.writeShort(AS_TRANS);
+ } else {
+ // write AS number in next 2-octet
+ cb.writeShort(message.asNumber);
+ }
// write HoldTime in next 2-octet
cb.writeShort(message.holdTime);
diff --git a/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java b/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java
new file mode 100755
index 0000000..6157028
--- /dev/null
+++ b/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/FourOctetAsNumCapabilityTlv.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 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 java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides FourOctetAsNumCapabilityTlv Capability Tlv.
+ */
+public class FourOctetAsNumCapabilityTlv implements BGPValueType {
+
+ /**
+ * support to indicate its support for four-octet AS numbers -CAPABILITY TLV format.
+ */
+ protected static final Logger log = LoggerFactory
+ .getLogger(FourOctetAsNumCapabilityTlv.class);
+
+ public static final byte TYPE = 65;
+ public static final byte LENGTH = 4;
+
+ private final int rawValue;
+
+ /**
+ * constructor to initialize rawValue.
+ * @param rawValue FourOctetAsNumCapabilityTlv
+ */
+ public FourOctetAsNumCapabilityTlv(int rawValue) {
+ this.rawValue = rawValue;
+ }
+
+ /**
+ * constructor to initialize raw.
+ * @param raw AS number
+ * @return object of FourOctetAsNumCapabilityTlv
+ */
+ public static FourOctetAsNumCapabilityTlv of(final int raw) {
+ return new FourOctetAsNumCapabilityTlv(raw);
+ }
+
+ /**
+ * Returns value of TLV.
+ * @return int value of rawValue
+ */
+ public int getInt() {
+ return rawValue;
+ }
+
+ @Override
+ public short getType() {
+ return TYPE;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rawValue);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof FourOctetAsNumCapabilityTlv) {
+ FourOctetAsNumCapabilityTlv other = (FourOctetAsNumCapabilityTlv) obj;
+ return Objects.equals(rawValue, other.rawValue);
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ int iLenStartIndex = cb.writerIndex();
+ cb.writeByte(TYPE);
+ cb.writeByte(LENGTH);
+ cb.writeInt(rawValue);
+ return cb.writerIndex() - iLenStartIndex;
+ }
+
+ /**
+ * Reads the channel buffer and returns object of FourOctetAsNumCapabilityTlv.
+ * @param cb type of channel buffer
+ * @return object of FourOctetAsNumCapabilityTlv
+ */
+ public static FourOctetAsNumCapabilityTlv read(ChannelBuffer cb) {
+ return FourOctetAsNumCapabilityTlv.of(cb.readInt());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("Type", TYPE)
+ .add("Length", LENGTH)
+ .add("Value", rawValue).toString();
+ }
+}
diff --git a/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java b/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java
new file mode 100755
index 0000000..9beff68
--- /dev/null
+++ b/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MultiProtocolExtnCapabilityTlv.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2015 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 java.util.Objects;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides MultiProtocolExtnCapabilityTlv.
+ */
+public class MultiProtocolExtnCapabilityTlv implements BGPValueType {
+
+ /*
+ 0 7 15 23 31
+ +-------+-------+-------+-------+
+ | AFI | Res | SAFI |
+ +-------+-------+-------+-------+
+
+ Multiprotocol Extensions CAPABILITY TLV format
+ REFERENCE : RFC 4760
+ */
+ protected static final Logger log = LoggerFactory
+ .getLogger(MultiProtocolExtnCapabilityTlv.class);
+
+ public static final byte TYPE = 1;
+ public static final byte LENGTH = 4;
+
+ private final short afi;
+ private final byte res;
+ private final byte safi;
+
+ /**
+ * Constructor to initialize variables.
+ * @param afi Address Family Identifiers
+ * @param res reserved field
+ * @param safi Subsequent Address Family Identifier
+ */
+ public MultiProtocolExtnCapabilityTlv(short afi, byte res, byte safi) {
+ this.afi = afi;
+ this.res = res;
+ this.safi = safi;
+ }
+
+ /**
+ * Returns object of MultiProtocolExtnCapabilityTlv.
+ * @param afi Address Family Identifiers
+ * @param res reserved field
+ * @param safi Subsequent Address Family Identifier
+ * @return object of MultiProtocolExtnCapabilityTlv
+ */
+ public static MultiProtocolExtnCapabilityTlv of(short afi, byte res,
+ byte safi) {
+ return new MultiProtocolExtnCapabilityTlv(afi, res, safi);
+ }
+
+ /**
+ * Returns afi Address Family Identifiers value.
+ * @return afi Address Family Identifiers value
+ */
+ public short getAFI() {
+ return afi;
+ }
+
+ /**
+ * Returns res reserved field value.
+ * @return res reserved field value
+ */
+ public byte getRes() {
+ return res;
+ }
+
+ /**
+ * Returns safi Subsequent Address Family Identifier value.
+ * @return safi Subsequent Address Family Identifier value
+ */
+ public byte getSAFI() {
+ return safi;
+ }
+
+ @Override
+ public short getType() {
+ return TYPE;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(afi, res, safi);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MultiProtocolExtnCapabilityTlv) {
+ MultiProtocolExtnCapabilityTlv other = (MultiProtocolExtnCapabilityTlv) obj;
+ return Objects.equals(this.afi, other.afi)
+ && Objects.equals(this.res, other.res)
+ && Objects.equals(this.safi, other.safi);
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ int iLenStartIndex = cb.writerIndex();
+ cb.writeByte(TYPE);
+ cb.writeByte(LENGTH);
+
+ // write afi
+ cb.writeShort(afi);
+
+ // write res
+ cb.writeByte(res);
+
+ // write safi
+ cb.writeByte(safi);
+
+ return cb.writerIndex() - iLenStartIndex;
+ }
+
+ /**
+ * Reads from channel buffer and returns object of MultiprotocolCapabilityTlv.
+ * @param cb of type channel buffer
+ * @return object of MultiProtocolExtnCapabilityTlv
+ */
+ public static BGPValueType read(ChannelBuffer cb) {
+ short afi = cb.readShort();
+ byte res = cb.readByte();
+ byte safi = cb.readByte();
+ return new MultiProtocolExtnCapabilityTlv(afi, res, safi);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("Type", TYPE)
+ .add("Length", LENGTH)
+ .add("AFI", afi)
+ .add("Reserved", res)
+ .add("SAFI", safi).toString();
+ }
+}