diff options
Diffstat (limited to 'framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4')
3 files changed, 369 insertions, 48 deletions
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPKeepaliveMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPKeepaliveMsgVer4.java index a6668b3a..10e6bb95 100644 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPKeepaliveMsgVer4.java +++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPKeepaliveMsgVer4.java @@ -98,21 +98,6 @@ class BGPKeepaliveMsgVer4 implements BGPKeepaliveMsg { BGPHeader bgpMsgHeader; @Override - public BGPVersion getVersion() { - return BGPVersion.BGP_4; - } - - @Override - public BGPType getType() { - return BGPType.KEEP_ALIVE; - } - - @Override - public BGPHeader getHeader() { - return this.bgpMsgHeader; - } - - @Override public Builder setHeader(BGPHeader bgpMsgHeader) { this.bgpMsgHeader = bgpMsgHeader; return this; diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java new file mode 100644 index 00000000..064deada --- /dev/null +++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java @@ -0,0 +1,266 @@ +/* + * 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.protocol.ver4; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.onosproject.bgpio.exceptions.BGPParseException; +import org.onosproject.bgpio.protocol.BGPMessageReader; +import org.onosproject.bgpio.protocol.BGPMessageWriter; +import org.onosproject.bgpio.protocol.BGPNotificationMsg; +import org.onosproject.bgpio.protocol.BGPType; +import org.onosproject.bgpio.protocol.BGPVersion; +import org.onosproject.bgpio.types.BGPErrorType; +import org.onosproject.bgpio.types.BGPHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.MoreObjects; + +/** + * A NOTIFICATION message is sent when an error condition is detected. The BGP connection is closed immediately after it + * is sent. + */ +class BGPNotificationMsgVer4 implements BGPNotificationMsg { + + /* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Error code | Error subcode | Data (variable) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + REFERENCE : RFC 4271 + */ + + protected static final Logger log = LoggerFactory.getLogger(BGPNotificationMsgVer4.class); + + static final byte PACKET_VERSION = 4; + //BGPHeader(19) + Error code(1) + Error subcode(1) + static final int TOTAL_MESSAGE_MIN_LENGTH = 21; + static final int PACKET_MINIMUM_LENGTH = 2; + static final BGPType MSG_TYPE = BGPType.NOTIFICATION; + static final byte DEFAULT_ERRORSUBCODE = 0; + static final byte[] MARKER = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01}; + static final byte MESSAGE_TYPE = 3; + static final BGPHeader DEFAULT_MESSAGE_HEADER = new BGPHeader(MARKER, BGPHeader.DEFAULT_HEADER_LENGTH, + MESSAGE_TYPE); + + private byte errorCode; + private byte errorSubCode; + private byte[] data; + private BGPHeader bgpHeader; + public static final BGPNotificationMsgVer4.Reader READER = new Reader(); + + /** + * Resets fields. + */ + public BGPNotificationMsgVer4() { + this.bgpHeader = null; + this.data = null; + this.errorCode = 0; + this.errorSubCode = 0; + } + + /** + * Constructor to initialize parameters. + * + * @param bgpHeader BGP Header in notification message + * @param errorCode error code + * @param errorSubCode error subcode + * @param data field + */ + public BGPNotificationMsgVer4(BGPHeader bgpHeader, byte errorCode, byte errorSubCode, byte[] data) { + this.bgpHeader = bgpHeader; + this.data = data; + this.errorCode = errorCode; + this.errorSubCode = errorSubCode; + } + + /** + * Reader reads BGP Notification Message from the channel buffer. + */ + static class Reader implements BGPMessageReader<BGPNotificationMsg> { + @Override + public BGPNotificationMsg readFrom(ChannelBuffer cb, BGPHeader bgpHeader) throws BGPParseException { + byte errorCode; + byte errorSubCode; + if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) { + throw new BGPParseException("Not enough readable bytes"); + } + errorCode = cb.readByte(); + errorSubCode = cb.readByte(); + //Message Length = 21 + Data Length + int dataLength = bgpHeader.getLength() - TOTAL_MESSAGE_MIN_LENGTH; + byte[] data = new byte[dataLength]; + cb.readBytes(data, 0, dataLength); + return new BGPNotificationMsgVer4(bgpHeader, errorCode, errorSubCode, data); + } + } + + /** + * Builder class for BGP notification message. + */ + static class Builder implements BGPNotificationMsg.Builder { + private byte errorCode; + private byte errorSubCode; + private byte[] data; + private BGPHeader bgpHeader; + private boolean isErrorCodeSet = false; + private boolean isErrorSubCodeSet = false; + private boolean isBGPHeaderSet = false; + + @Override + public BGPNotificationMsg build() throws BGPParseException { + BGPHeader bgpHeader = this.isBGPHeaderSet ? this.bgpHeader : DEFAULT_MESSAGE_HEADER; + if (!this.isErrorCodeSet) { + throw new BGPParseException("Error code must be present"); + } + + byte errorSubCode = this.isErrorSubCodeSet ? this.errorSubCode : DEFAULT_ERRORSUBCODE; + return new BGPNotificationMsgVer4(bgpHeader, this.errorCode, errorSubCode, this.data); + } + + @Override + public Builder setErrorCode(byte errorCode) { + this.errorCode = errorCode; + this.isErrorCodeSet = true; + return this; + } + + @Override + public Builder setErrorSubCode(byte errorSubCode) { + this.errorSubCode = errorSubCode; + this.isErrorSubCodeSet = true; + return this; + } + + @Override + public Builder setData(byte[] data) { + this.data = data; + return this; + } + + @Override + public Builder setNotificationMsgHeader(BGPHeader header) { + this.bgpHeader = header; + this.isBGPHeaderSet = true; + return this; + } + + @Override + public Builder setHeader(BGPHeader bgpMsgHeader) { + this.bgpHeader = bgpMsgHeader; + return this; + } + } + + @Override + public BGPVersion getVersion() { + return BGPVersion.BGP_4; + } + + @Override + public BGPType getType() { + return BGPType.NOTIFICATION; + } + + @Override + public void writeTo(ChannelBuffer cb) throws BGPParseException { + WRITER.write(cb, this); + } + + static final Writer WRITER = new Writer(); + + /** + * Writer writes BGP notification message to channel buffer. + */ + static class Writer implements BGPMessageWriter<BGPNotificationMsgVer4> { + @Override + public void write(ChannelBuffer cb, BGPNotificationMsgVer4 message) throws BGPParseException { + int msgStartIndex = cb.writerIndex(); + int headerLenIndex = message.bgpHeader.write(cb); + if (headerLenIndex <= 0) { + throw new BGPParseException(BGPErrorType.MESSAGE_HEADER_ERROR, (byte) 0, null); + } + cb.writeByte(message.errorCode); + cb.writeByte(message.errorSubCode); + cb.writeBytes(message.data); + + //Update message length field in notification message + int length = cb.writerIndex() - msgStartIndex; + cb.setShort(headerLenIndex, (short) length); + message.bgpHeader.setLength((short) length); + } + } + + @Override + public byte getErrorCode() { + return this.errorCode; + } + + /** + * Sets errorcode with specified errorcode. + * + * @param errorCode field + */ + public void setErrorCode(byte errorCode) { + this.errorCode = errorCode; + } + + @Override + public byte getErrorSubCode() { + return this.errorSubCode; + } + + /** + * Sets error subcode with specified errorSubCode. + * + * @param errorSubCode field + */ + public void setErrorSubCode(byte errorSubCode) { + this.errorSubCode = errorSubCode; + } + + @Override + public byte[] getData() { + return this.data; + } + + /** + * Sets error data with specified data. + * + * @param data field + */ + public void setData(byte[] data) { + this.data = data; + } + + @Override + public BGPHeader getHeader() { + return this.bgpHeader; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .omitNullValues() + .add("bgpHeader", bgpHeader) + .add("data", data) + .add("errorCode", errorCode) + .add("errorSubCode", errorSubCode) + .toString(); + } +}
\ No newline at end of file diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java index 1348ecfd..b50342d6 100644 --- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPOpenMsgVer4.java +++ b/framework/src/onos/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.protocol.BGPVersion; 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 class BGPOpenMsgVer4 implements BGPOpenMsg { 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 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { 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 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { /** * 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 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { 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 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { 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,34 +309,30 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { 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); } @Override - public BGPHeader getHeader() { - return this.bgpMsgHeader; - } - - @Override public Builder setHeader(BGPHeader bgpMsgHeader) { this.bgpMsgHeader = bgpMsgHeader; return this; } @Override - public BGPVersion getVersion() { - return BGPVersion.BGP_4; - } - - @Override - public BGPType getType() { - return MSG_TYPE; - } - - @Override public short getHoldTime() { return this.holdTime; } @@ -342,6 +378,18 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { 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 +412,7 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { public void write(ChannelBuffer cb, BGPOpenMsgVer4 message) throws BGPParseException { int optParaLen = 0; + int as4num = 0; int startIndex = cb.writerIndex(); @@ -377,8 +426,29 @@ public class BGPOpenMsgVer4 implements BGPOpenMsg { // 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); |