blob: d60adceefb17a170d1a5c935c6172649b5ac33f7 [file] [log] [blame]
/*
* Copyright 2015-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.protocol.ver4;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.types.As4Path;
import org.onosproject.bgpio.types.AsPath;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpExtendedCommunity;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.LinkStateAttributes;
import org.onosproject.bgpio.types.LocalPref;
import org.onosproject.bgpio.types.Med;
import org.onosproject.bgpio.types.NextHop;
import org.onosproject.bgpio.types.Origin;
import org.onosproject.bgpio.types.MpReachNlri;
import org.onosproject.bgpio.types.MpUnReachNlri;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.onosproject.bgpio.util.Validation;
import org.onosproject.bgpio.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
/**
* Provides Implementation of BGP Path Attribute.
*/
public class BgpPathAttributes {
/* Path attribute:
<attribute type, attribute length, attribute value>
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attr. Flags |Attr. Type Code|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
REFERENCE : RFC 4271
*/
protected static final Logger log = LoggerFactory.getLogger(BgpPathAttributes.class);
public static final int LINK_STATE_ATTRIBUTE_TYPE = 29;
public static final int MPREACHNLRI_TYPE = 14;
public static final int MPUNREACHNLRI_TYPE = 15;
public static final int EXTENDED_COMMUNITY_TYPE = 16;
private final List<BgpValueType> pathAttribute;
/**
* Initialize parameter.
*/
public BgpPathAttributes() {
this.pathAttribute = null;
}
/**
* Constructor to initialize parameters for BGP path attributes.
*
* @param pathAttribute list of path attributes
*/
public BgpPathAttributes(List<BgpValueType> pathAttribute) {
this.pathAttribute = pathAttribute;
}
/**
* Returns list of path attributes.
*
* @return list of path attributes
*/
public List<BgpValueType> pathAttributes() {
return this.pathAttribute;
}
/**
* Reads from channelBuffer and parses BGP path attributes.
*
* @param cb channelBuffer
* @return object of BgpPathAttributes
* @throws BgpParseException while parsing BGP path attributes
*/
public static BgpPathAttributes read(ChannelBuffer cb)
throws BgpParseException {
BgpValueType pathAttribute = null;
List<BgpValueType> pathAttributeList = new LinkedList<>();
boolean isOrigin = false;
boolean isAsPath = false;
boolean isNextHop = false;
boolean isMpReach = false;
boolean isMpUnReach = false;
while (cb.readableBytes() > 0) {
cb.markReaderIndex();
byte flags = cb.readByte();
byte typeCode = cb.readByte();
cb.resetReaderIndex();
switch (typeCode) {
case Origin.ORIGIN_TYPE:
pathAttribute = Origin.read(cb);
isOrigin = ((Origin) pathAttribute).isOriginSet();
break;
case AsPath.ASPATH_TYPE:
pathAttribute = AsPath.read(cb);
isAsPath = ((AsPath) pathAttribute).isaspathSet();
break;
case As4Path.AS4PATH_TYPE:
pathAttribute = As4Path.read(cb);
break;
case NextHop.NEXTHOP_TYPE:
pathAttribute = NextHop.read(cb);
isNextHop = ((NextHop) pathAttribute).isNextHopSet();
break;
case Med.MED_TYPE:
pathAttribute = Med.read(cb);
break;
case LocalPref.LOCAL_PREF_TYPE:
pathAttribute = LocalPref.read(cb);
break;
case MpReachNlri.MPREACHNLRI_TYPE:
pathAttribute = MpReachNlri.read(cb);
isMpReach = ((MpReachNlri) pathAttribute).isMpReachNlriSet();
break;
case MpUnReachNlri.MPUNREACHNLRI_TYPE:
pathAttribute = MpUnReachNlri.read(cb);
isMpUnReach = ((MpUnReachNlri) pathAttribute)
.isMpUnReachNlriSet();
break;
case LINK_STATE_ATTRIBUTE_TYPE:
pathAttribute = LinkStateAttributes.read(cb);
break;
case EXTENDED_COMMUNITY_TYPE:
pathAttribute = BgpExtendedCommunity.read(cb);
break;
default:
//skip bytes for unsupported attribute types
UnSupportedAttribute.read(cb);
}
pathAttributeList.add(pathAttribute);
}
checkMandatoryAttr(isOrigin, isAsPath, isNextHop, isMpReach, isMpUnReach);
//TODO:if mp_reach or mp_unreach not present ignore the packet
return new BgpPathAttributes(pathAttributeList);
}
/**
* Write path attributes to channelBuffer.
*
* @param cb channelBuffer
* @return object of BgpPathAttributes
* @throws BgpParseException while parsing BGP path attributes
*/
public int write(ChannelBuffer cb)
throws BgpParseException {
if (pathAttribute == null) {
return 0;
}
int iLenStartIndex = cb.writerIndex();
ListIterator<BgpValueType> iterator = pathAttribute.listIterator();
int pathAttributeIndx = cb.writerIndex();
cb.writeShort(0);
while (iterator.hasNext()) {
BgpValueType attr = iterator.next();
switch (attr.getType()) {
case Origin.ORIGIN_TYPE:
Origin origin = (Origin) attr;
origin.write(cb);
break;
case AsPath.ASPATH_TYPE:
AsPath asPath = (AsPath) attr;
asPath.write(cb);
break;
case As4Path.AS4PATH_TYPE:
As4Path as4Path = (As4Path) attr;
as4Path.write(cb);
break;
case NextHop.NEXTHOP_TYPE:
NextHop nextHop = (NextHop) attr;
nextHop.write(cb);
break;
case Med.MED_TYPE:
Med med = (Med) attr;
med.write(cb);
break;
case LocalPref.LOCAL_PREF_TYPE:
LocalPref localPref = (LocalPref) attr;
localPref.write(cb);
break;
case Constants.BGP_EXTENDED_COMMUNITY:
BgpExtendedCommunity extendedCommunity = (BgpExtendedCommunity) attr;
extendedCommunity.write(cb);
break;
case MpReachNlri.MPREACHNLRI_TYPE:
MpReachNlri mpReach = (MpReachNlri) attr;
mpReach.write(cb);
break;
case MpUnReachNlri.MPUNREACHNLRI_TYPE:
MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
mpUnReach.write(cb);
break;
case LINK_STATE_ATTRIBUTE_TYPE:
LinkStateAttributes linkState = (LinkStateAttributes) attr;
linkState.write(cb);
break;
default:
return cb.writerIndex() - iLenStartIndex;
}
}
int pathAttrLen = cb.writerIndex() - pathAttributeIndx;
cb.setShort(pathAttributeIndx, (short) (pathAttrLen - 2));
return cb.writerIndex() - iLenStartIndex;
}
/**
* Checks mandatory attributes are presents, if not present throws exception.
*
* @param isOrigin say whether origin attribute is present
* @param isAsPath say whether aspath attribute is present
* @param isNextHop say whether nexthop attribute is present
* @param isMpReach say whether mpreach attribute is present
* @param isMpUnReach say whether mpunreach attribute is present
* @throws BgpParseException if mandatory path attribute is not present
*/
public static void checkMandatoryAttr(boolean isOrigin, boolean isAsPath,
boolean isNextHop, boolean isMpReach, boolean isMpUnReach)
throws BgpParseException {
// Mandatory attributes validation not required for MP_UNREACH
if (isMpUnReach) {
return;
}
if (!isOrigin) {
log.debug("Mandatory Attributes not Present");
Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR,
BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
Origin.ORIGIN_TYPE);
}
if (!isAsPath) {
log.debug("Mandatory Attributes not Present");
Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR,
BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
AsPath.ASPATH_TYPE);
}
if (!isMpUnReach && !isMpReach && !isNextHop) {
log.debug("Mandatory Attributes not Present");
Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR,
BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
NextHop.NEXTHOP_TYPE);
}
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("pathAttribute", pathAttribute)
.toString();
}
}