Shashikanth VH
Committed by Gerrit Code Review

[ONOS-4241]Codec for wide community and flow spec

Change-Id: I2dfd6b88c4ae14a02d258a2cdc9ee35b9ff08292
Showing 13 changed files with 350 additions and 709 deletions
......@@ -19,9 +19,10 @@ import org.jboss.netty.channel.Channel;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpFactory;
import org.onosproject.bgpio.protocol.BgpMessage;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecRouteKey;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.attr.WideCommunity;
/**
* Represents the peer side of an BGP peer.
......@@ -124,14 +125,6 @@ public interface BgpPeer {
void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException;
/**
* Update flow specification RIB for each peer.
*
* @param pathAttr list of Bgp path attributes
* @throws BgpParseException while building flow spec RIB
*/
void buildFlowSpecRib(List<BgpValueType> pathAttr) throws BgpParseException;
/**
* Return the BGP session info.
*
* @return sessionInfo bgp session info
......@@ -142,9 +135,10 @@ public interface BgpPeer {
* Updates flow specification rule.
*
* @param operType operation type add or delete or update
* @param prefix prefix for the flow rule
* @param routeKey flow route key for the flow rule
* @param flowSpec BGP flow specification components
* @param wideCommunity for route policy
*/
void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecPrefix prefix,
BgpFlowSpecDetails flowSpec);
void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity);
}
......
......@@ -17,25 +17,44 @@ package org.onosproject.bgpio.protocol.flowspec;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onosproject.bgpio.types.BgpFsDestinationPortNum;
import org.onosproject.bgpio.types.BgpFsDestinationPrefix;
import org.onosproject.bgpio.types.BgpFsDscpValue;
import org.onosproject.bgpio.types.BgpFsFragment;
import org.onosproject.bgpio.types.BgpFsIcmpCode;
import org.onosproject.bgpio.types.BgpFsIcmpType;
import org.onosproject.bgpio.types.BgpFsIpProtocol;
import org.onosproject.bgpio.types.BgpFsPacketLength;
import org.onosproject.bgpio.types.BgpFsPortNum;
import org.onosproject.bgpio.types.BgpFsSourcePortNum;
import org.onosproject.bgpio.types.BgpFsSourcePrefix;
import org.onosproject.bgpio.types.BgpFsTcpFlags;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.RouteDistinguisher;
import org.onosproject.bgpio.util.Constants;
import com.google.common.base.MoreObjects;
/**
* This Class stores flow specification components and action.
*/
public class BgpFlowSpecDetails {
public class BgpFlowSpecNlri {
private List<BgpValueType> flowSpecComponents;
private List<BgpValueType> fsActionTlv;
private RouteDistinguisher routeDistinguisher;
public static final short FLOW_SPEC_LEN = 240;
/**
* Flow specification details object constructor with the parameter.
*
* @param flowSpecComponents flow specification components
*/
public BgpFlowSpecDetails(List<BgpValueType> flowSpecComponents) {
public BgpFlowSpecNlri(List<BgpValueType> flowSpecComponents) {
this.flowSpecComponents = flowSpecComponents;
}
......@@ -43,7 +62,7 @@ public class BgpFlowSpecDetails {
* Flow specification details object constructor.
*
*/
public BgpFlowSpecDetails() {
public BgpFlowSpecNlri() {
}
......@@ -112,11 +131,11 @@ public class BgpFlowSpecDetails {
return true;
}
if (obj instanceof BgpFlowSpecDetails) {
if (obj instanceof BgpFlowSpecNlri) {
int countObjSubTlv = 0;
int countOtherSubTlv = 0;
boolean isCommonSubTlv = true;
BgpFlowSpecDetails other = (BgpFlowSpecDetails) obj;
BgpFlowSpecNlri other = (BgpFlowSpecNlri) obj;
Iterator<BgpValueType> objListIterator = other.flowSpecComponents.iterator();
countOtherSubTlv = other.flowSpecComponents.size();
countObjSubTlv = flowSpecComponents.size();
......@@ -138,6 +157,133 @@ public class BgpFlowSpecDetails {
return false;
}
/**
* Write flow type to channel buffer.
*
* @param tlv flow type
* @param cb channel buffer
*/
public static void writeFlowType(BgpValueType tlv, ChannelBuffer cb) {
switch (tlv.getType()) {
case Constants.BGP_FLOWSPEC_DST_PREFIX:
BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
fsDstPrefix.write(cb);
break;
case Constants.BGP_FLOWSPEC_SRC_PREFIX:
BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
fsSrcPrefix.write(cb);
break;
case Constants.BGP_FLOWSPEC_IP_PROTO:
BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
fsIpProtocol.write(cb);
break;
case Constants.BGP_FLOWSPEC_PORT:
BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
fsPortNum.write(cb);
break;
case Constants.BGP_FLOWSPEC_DST_PORT:
BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
fsDstPortNum.write(cb);
break;
case Constants.BGP_FLOWSPEC_SRC_PORT:
BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
fsSrcPortNum.write(cb);
break;
case Constants.BGP_FLOWSPEC_ICMP_TP:
BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
fsIcmpType.write(cb);
break;
case Constants.BGP_FLOWSPEC_ICMP_CD:
BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
fsIcmpCode.write(cb);
break;
case Constants.BGP_FLOWSPEC_TCP_FLAGS:
BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
fsTcpFlags.write(cb);
break;
case Constants.BGP_FLOWSPEC_PCK_LEN:
BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
fsPacketLen.write(cb);
break;
case Constants.BGP_FLOWSPEC_DSCP:
BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
fsDscpVal.write(cb);
break;
case Constants.BGP_FLOWSPEC_FRAGMENT:
BgpFsFragment fsFragment = (BgpFsFragment) tlv;
fsFragment.write(cb);
break;
default:
break;
}
return;
}
/**
* Update buffer with identical flow types.
*
* @param cb channel buffer
*/
public static void updateBufferIdenticalFlowTypes(ChannelBuffer cb, BgpFlowSpecNlri bgpFlowSpecNlri) {
List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
while (listIterator.hasNext()) {
ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
BgpValueType tlv = listIterator.next();
writeFlowType(tlv, flowSpecTmpBuff);
/* RFC 5575: section 4, If the NLRI length value is smaller than 240 (0xf0 hex), the length
field can be encoded as a single octet. Otherwise, it is encoded as
an extended-length 2-octet values */
int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
if (len >= FLOW_SPEC_LEN) {
cb.writeShort(len);
} else {
cb.writeByte(len);
}
//Copy from bynamic buffer to channel buffer
cb.writeBytes(flowSpecTmpBuff);
}
return;
}
/**
* Update buffer with non-identical flow types.
*
* @param cb channel buffer
*/
public static void updateBufferNonIdenticalFlowTypes(ChannelBuffer cb, BgpFlowSpecNlri bgpFlowSpecNlri) {
ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
flowSpec = bgpFlowSpecNlri.flowSpecComponents();
listIterator = flowSpec.listIterator();
while (listIterator.hasNext()) {
BgpValueType tlv = listIterator.next();
writeFlowType(tlv, flowSpecTmpBuff);
}
/* RFC 5575: section 4, If the NLRI length value is smaller than 240 (0xf0 hex), the length
field can be encoded as a single octet. Otherwise, it is encoded as
an extended-length 2-octet values */
int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
if (len >= FLOW_SPEC_LEN) {
cb.writeShort(len);
} else {
cb.writeByte(len);
}
//Copy from bynamic buffer to channel buffer
cb.writeBytes(flowSpecTmpBuff);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
......
......@@ -17,45 +17,41 @@
package org.onosproject.bgpio.protocol.flowspec;
import java.util.Objects;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import com.google.common.base.MoreObjects;
/**
* Provides BGP flow specification rule index.
* Provides BGP flow specification route index.
*/
public class BgpFlowSpecPrefix implements Comparable<Object> {
public class BgpFlowSpecRouteKey implements Comparable<Object> {
private static final Logger log = LoggerFactory.getLogger(BgpFlowSpecPrefix.class);
private static final Logger log = LoggerFactory.getLogger(BgpFlowSpecRouteKey.class);
private final IpPrefix destinationPrefix;
private final IpPrefix sourcePrefix;
private final String routeKey;
/**
* Constructor to initialize parameters.
*
* @param destinationPrefix destination prefix
* @param sourcePrefix source prefix
* @param routeKey route key
*/
public BgpFlowSpecPrefix(IpPrefix destinationPrefix, IpPrefix sourcePrefix) {
if (destinationPrefix == null) {
destinationPrefix = IpPrefix.valueOf(0, 0);
public BgpFlowSpecRouteKey(String routeKey) {
this.routeKey = routeKey;
}
if (sourcePrefix == null) {
sourcePrefix = IpPrefix.valueOf(0, 0);
}
this.destinationPrefix = destinationPrefix;
this.sourcePrefix = sourcePrefix;
/**
* Returns route key.
*
* @return route key
*/
public String routeKey() {
return this.routeKey;
}
@Override
public int hashCode() {
return Objects.hash(destinationPrefix, sourcePrefix);
return Objects.hashCode(routeKey);
}
@Override
......@@ -63,93 +59,33 @@ public class BgpFlowSpecPrefix implements Comparable<Object> {
if (this == obj) {
return true;
}
if (obj instanceof BgpFlowSpecPrefix) {
BgpFlowSpecPrefix other = (BgpFlowSpecPrefix) obj;
if ((this.destinationPrefix != null) && (this.sourcePrefix != null)
&& (this.destinationPrefix.equals(other.destinationPrefix))) {
return this.sourcePrefix.equals(other.sourcePrefix);
} else if (this.destinationPrefix != null) {
return this.destinationPrefix.equals(other.destinationPrefix);
} else if (this.sourcePrefix != null) {
return this.sourcePrefix.equals(other.sourcePrefix);
}
return false;
if (obj instanceof BgpFlowSpecRouteKey) {
BgpFlowSpecRouteKey other = (BgpFlowSpecRouteKey) obj;
return this.routeKey.equals(other.routeKey);
}
return false;
}
/**
* Returns destination prefix.
*
* @return destination prefix
*/
public IpPrefix destinationPrefix() {
return this.destinationPrefix;
}
/**
* Returns source prefix.
*
* @return source prefix
*/
public IpPrefix sourcePrefix() {
return this.sourcePrefix;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass()).omitNullValues()
.add("destinationPrefix", destinationPrefix)
.add("sourcePrefix", destinationPrefix)
.toString();
}
/**
* Compares this and o object.
*
* @param o object to be compared with this object
* @return which object is greater
*/
public int compareTo(Object o) {
if (this.equals(o)) {
return 0;
}
if (o instanceof BgpFlowSpecPrefix) {
BgpFlowSpecPrefix that = (BgpFlowSpecPrefix) o;
if (this.destinationPrefix() != null) {
if (this.destinationPrefix().prefixLength() == that.destinationPrefix().prefixLength()) {
ByteBuffer value1 = ByteBuffer.wrap(this.destinationPrefix().address().toOctets());
ByteBuffer value2 = ByteBuffer.wrap(that.destinationPrefix().address().toOctets());
int cmpVal = value1.compareTo(value2);
if (cmpVal != 0) {
return cmpVal;
}
} else {
if (this.destinationPrefix().prefixLength() > that.destinationPrefix().prefixLength()) {
return 1;
} else if (this.destinationPrefix().prefixLength() < that.destinationPrefix().prefixLength()) {
return -1;
}
}
}
if (this.sourcePrefix() != null) {
if (this.sourcePrefix().prefixLength() == that.sourcePrefix().prefixLength()) {
ByteBuffer value1 = ByteBuffer.wrap(this.sourcePrefix().address().toOctets());
ByteBuffer value2 = ByteBuffer.wrap(that.sourcePrefix().address().toOctets());
return value1.compareTo(value2);
}
if (this.sourcePrefix().prefixLength() > that.sourcePrefix().prefixLength()) {
return 1;
} else if (this.sourcePrefix().prefixLength() < that.sourcePrefix().prefixLength()) {
return -1;
}
if (o instanceof BgpFlowSpecRouteKey) {
BgpFlowSpecRouteKey other = (BgpFlowSpecRouteKey) o;
if (this.routeKey.compareTo(other.routeKey) != 0) {
return this.routeKey.compareTo(other.routeKey);
}
return 0;
}
return 1;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass()).omitNullValues()
.add("routeKey", routeKey)
.toString();
}
}
......
......@@ -22,11 +22,10 @@ import java.util.List;
import java.util.ListIterator;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onlab.packet.Ip4Address;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpLSNlri;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
......@@ -46,14 +45,13 @@ public class MpReachNlri implements BgpValueType {
public static final byte MPREACHNLRI_TYPE = 14;
public static final byte LINK_NLRITYPE = 2;
public static final byte FLAGS = (byte) 0x90;
public static final short FLOW_SPEC_LEN = 240;
private boolean isMpReachNlri = false;
private final List<BgpLSNlri> mpReachNlri;
private final int length;
private final short afi;
private final byte safi;
private final Ip4Address ipNextHop;
private BgpFlowSpecDetails bgpFlowSpecInfo;
private BgpFlowSpecNlri bgpFlowSpecNlri;
/**
* Constructor to initialize parameters.
......@@ -73,12 +71,12 @@ public class MpReachNlri implements BgpValueType {
this.length = length;
}
public MpReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
public MpReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
this.mpReachNlri = null;
this.isMpReachNlri = true;
this.length = 0;
this.ipNextHop = null;
this.bgpFlowSpecInfo = bgpFlowSpecInfo;
this.bgpFlowSpecNlri = bgpFlowSpecNlri;
this.afi = afi;
this.safi = safi;
}
......@@ -115,8 +113,8 @@ public class MpReachNlri implements BgpValueType {
*
* @return BGP flow specification info
*/
public BgpFlowSpecDetails bgpFlowSpecInfo() {
return this.bgpFlowSpecInfo;
public BgpFlowSpecNlri bgpFlowSpecNlri() {
return this.bgpFlowSpecNlri;
}
/**
......@@ -208,8 +206,13 @@ public class MpReachNlri implements BgpValueType {
routeDistinguisher = new RouteDistinguisher();
routeDistinguisher = RouteDistinguisher.read(tempCb);
}
while (tempCb.readableBytes() > 0) {
short totNlriLen = tempCb.getByte(tempCb.readerIndex());
if (totNlriLen >= FLOW_SPEC_LEN) {
if (totNlriLen >= BgpFlowSpecNlri.FLOW_SPEC_LEN) {
if (tempCb.readableBytes() < 2) {
Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
}
totNlriLen = tempCb.readShort();
} else {
totNlriLen = tempCb.readByte();
......@@ -265,7 +268,8 @@ public class MpReachNlri implements BgpValueType {
flowSpecComponents.add(flowSpecComponent);
}
}
BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
}
BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
return new MpReachNlri(flowSpecDetails, afi, safi);
} else {
......@@ -310,8 +314,12 @@ public class MpReachNlri implements BgpValueType {
@Override
public int write(ChannelBuffer cb) {
int iLenStartIndex = cb.writerIndex();
if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
|| (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
boolean isAllFlowTypesIdentical = true;
cb.writeByte(FLAGS);
cb.writeByte(MPREACHNLRI_TYPE);
......@@ -326,84 +334,27 @@ public class MpReachNlri implements BgpValueType {
//sub network points of attachment
cb.writeByte(0);
if (bgpFlowSpecInfo.routeDistinguisher() != null) {
cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
if (bgpFlowSpecNlri.routeDistinguisher() != null) {
cb.writeLong(bgpFlowSpecNlri.routeDistinguisher().getRouteDistinguisher());
}
ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
BgpValueType tlv1 = null;
if (listIterator.hasNext()) {
tlv1 = listIterator.next();
}
while (listIterator.hasNext()) {
BgpValueType tlv = listIterator.next();
switch (tlv.getType()) {
case Constants.BGP_FLOWSPEC_DST_PREFIX:
BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
fsDstPrefix.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_SRC_PREFIX:
BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
fsSrcPrefix.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_IP_PROTO:
BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
fsIpProtocol.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_PORT:
BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
fsPortNum.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_DST_PORT:
BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
fsDstPortNum.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_SRC_PORT:
BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
fsSrcPortNum.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_ICMP_TP:
BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
fsIcmpType.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_ICMP_CD:
BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
fsIcmpCode.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_TCP_FLAGS:
BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
fsTcpFlags.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_PCK_LEN:
BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
fsPacketLen.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_DSCP:
BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
fsDscpVal.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_FRAGMENT:
BgpFsFragment fsFragment = (BgpFsFragment) tlv;
fsFragment.write(flowSpecTmpBuff);
break;
default:
if (tlv.getType() != tlv1.getType()) {
isAllFlowTypesIdentical = false;
break;
}
}
/* RFC 5575: section 4, If the NLRI length value is smaller than 240 (0xf0 hex), the length
field can be encoded as a single octet. Otherwise, it is encoded as
an extended-length 2-octet values */
int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
if (len >= FLOW_SPEC_LEN) {
cb.writeShort(len);
if (isAllFlowTypesIdentical) {
BgpFlowSpecNlri.updateBufferIdenticalFlowTypes(cb, bgpFlowSpecNlri());
} else {
cb.writeByte(len);
BgpFlowSpecNlri.updateBufferNonIdenticalFlowTypes(cb, bgpFlowSpecNlri());
}
//Copy from bynamic buffer to channel buffer
cb.writeBytes(flowSpecTmpBuff);
int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
......@@ -416,7 +367,7 @@ public class MpReachNlri implements BgpValueType {
public String toString() {
return MoreObjects.toStringHelper(getClass()).omitNullValues()
.add("mpReachNlri", mpReachNlri)
.add("bgpFlowSpecInfo", bgpFlowSpecInfo)
.add("bgpFlowSpecNlri", bgpFlowSpecNlri)
.add("afi", afi)
.add("safi", safi)
.add("ipNextHop", ipNextHop)
......
......@@ -21,10 +21,9 @@ import java.util.List;
import java.util.ListIterator;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpLSNlri;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
......@@ -44,13 +43,12 @@ public class MpUnReachNlri implements BgpValueType {
public static final byte MPUNREACHNLRI_TYPE = 15;
public static final byte LINK_NLRITYPE = 2;
public static final byte FLAGS = (byte) 0x90;
public static final short FLOW_SPEC_LEN = 240;
private boolean isMpUnReachNlri = false;
private final short afi;
private final byte safi;
private final List<BgpLSNlri> mpUnReachNlri;
private final int length;
private BgpFlowSpecDetails bgpFlowSpecInfo;
private BgpFlowSpecNlri bgpFlowSpecNlri;
/**
* Constructor to initialize parameters.
......@@ -69,11 +67,11 @@ public class MpUnReachNlri implements BgpValueType {
this.length = length;
}
public MpUnReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
public MpUnReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
this.mpUnReachNlri = null;
this.isMpUnReachNlri = true;
this.length = 0;
this.bgpFlowSpecInfo = bgpFlowSpecInfo;
this.bgpFlowSpecNlri = bgpFlowSpecNlri;
this.afi = afi;
this.safi = safi;
}
......@@ -83,8 +81,8 @@ public class MpUnReachNlri implements BgpValueType {
*
* @return BGP flow specification info
*/
public BgpFlowSpecDetails bgpFlowSpecInfo() {
return this.bgpFlowSpecInfo;
public BgpFlowSpecNlri bgpFlowSpecNlri() {
return this.bgpFlowSpecNlri;
}
/**
......@@ -162,8 +160,13 @@ public class MpUnReachNlri implements BgpValueType {
routeDistinguisher = new RouteDistinguisher();
routeDistinguisher = RouteDistinguisher.read(tempCb);
}
while (tempCb.readableBytes() > 0) {
short totNlriLen = tempCb.getByte(tempCb.readerIndex());
if (totNlriLen >= FLOW_SPEC_LEN) {
if (totNlriLen >= BgpFlowSpecNlri.FLOW_SPEC_LEN) {
if (tempCb.readableBytes() < 2) {
Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
}
totNlriLen = tempCb.readShort();
} else {
totNlriLen = tempCb.readByte();
......@@ -198,7 +201,7 @@ public class MpUnReachNlri implements BgpValueType {
flowSpecComponent = BgpFsIcmpType.read(tempBuf);
break;
case Constants.BGP_FLOWSPEC_ICMP_CD:
flowSpecComponent = BgpFsIcmpType.read(tempBuf);
flowSpecComponent = BgpFsIcmpCode.read(tempBuf);
break;
case Constants.BGP_FLOWSPEC_TCP_FLAGS:
flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
......@@ -219,7 +222,8 @@ public class MpUnReachNlri implements BgpValueType {
flowSpecComponents.add(flowSpecComponent);
}
}
BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
}
BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
return new MpUnReachNlri(flowSpecDetails, afi, safi);
} else {
......@@ -286,6 +290,9 @@ public class MpUnReachNlri implements BgpValueType {
int iLenStartIndex = cb.writerIndex();
if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE) ||
(safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
boolean isAllFlowTypesIdentical = true;
cb.writeByte(FLAGS);
cb.writeByte(MPUNREACHNLRI_TYPE);
......@@ -296,79 +303,27 @@ public class MpUnReachNlri implements BgpValueType {
cb.writeShort(afi);
cb.writeByte(safi);
if (bgpFlowSpecInfo.routeDistinguisher() != null) {
cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
if (bgpFlowSpecNlri.routeDistinguisher() != null) {
cb.writeLong(bgpFlowSpecNlri.routeDistinguisher().getRouteDistinguisher());
}
ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
BgpValueType tlv1 = null;
if (listIterator.hasNext()) {
tlv1 = listIterator.next();
}
while (listIterator.hasNext()) {
BgpValueType tlv = listIterator.next();
switch (tlv.getType()) {
case Constants.BGP_FLOWSPEC_DST_PREFIX:
BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
fsDstPrefix.write(flowSpecTmpBuff);
if (tlv.getType() != tlv1.getType()) {
isAllFlowTypesIdentical = false;
break;
case Constants.BGP_FLOWSPEC_SRC_PREFIX:
BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
fsSrcPrefix.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_IP_PROTO:
BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
fsIpProtocol.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_PORT:
BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
fsPortNum.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_DST_PORT:
BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
fsDstPortNum.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_SRC_PORT:
BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
fsSrcPortNum.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_ICMP_TP:
BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
fsIcmpType.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_ICMP_CD:
BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
fsIcmpCode.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_TCP_FLAGS:
BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
fsTcpFlags.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_PCK_LEN:
BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
fsPacketLen.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_DSCP:
BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
fsDscpVal.write(flowSpecTmpBuff);
break;
case Constants.BGP_FLOWSPEC_FRAGMENT:
BgpFsFragment fsFragment = (BgpFsFragment) tlv;
fsFragment.write(flowSpecTmpBuff);
break;
default:
}
}
int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
if (len >= FLOW_SPEC_LEN) {
cb.writeShort(len);
if (isAllFlowTypesIdentical) {
BgpFlowSpecNlri.updateBufferIdenticalFlowTypes(cb, bgpFlowSpecNlri());
} else {
cb.writeByte(len);
BgpFlowSpecNlri.updateBufferNonIdenticalFlowTypes(cb, bgpFlowSpecNlri());
}
//Copy from bynamic buffer to channel buffer
cb.writeBytes(flowSpecTmpBuff);
int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
}
......@@ -386,7 +341,7 @@ public class MpUnReachNlri implements BgpValueType {
public String toString() {
return MoreObjects.toStringHelper(getClass()).omitNullValues()
.add("mpReachNlri", mpUnReachNlri)
.add("bgpFlowSpecInfo", bgpFlowSpecInfo)
.add("bgpFlowSpecNlri", bgpFlowSpecNlri)
.add("afi", afi)
.add("safi", safi)
.add("length", length)
......
......@@ -64,6 +64,22 @@ public class RpdCapabilityTlv implements BgpValueType {
return sendReceive;
}
/**
* Returns address family identifier value.
* @return afi address family identifier value
*/
public short getAfi() {
return afi;
}
/**
* Returns subsequent address family identifier value.
* @return safi subsequent address family identifier value
*/
public byte getSafi() {
return sAfi;
}
@Override
public short getType() {
return TYPE;
......
......@@ -28,23 +28,23 @@ import org.onosproject.bgpio.types.BgpValueType;
import com.google.common.testing.EqualsTester;
/**
* Test for BgpFlowSpecDetails flow specification.
* Test for BgpFlowSpecNlri flow specification.
*/
public class BgpFlowSpecDetailsTest {
public class BgpFlowSpecNlriTest {
List<BgpValueType> flowSpecComponents1 = new LinkedList<>();
private List<BgpFsOperatorValue> operatorValue1 = new ArrayList<>();
BgpFlowSpecDetails flowSpecDetails1 = new BgpFlowSpecDetails(flowSpecComponents1);
BgpFlowSpecNlri flowSpecDetails1 = new BgpFlowSpecNlri(flowSpecComponents1);
BgpFsPortNum portNum1 = new BgpFsPortNum(operatorValue1);
List<BgpValueType> flowSpecComponents = new LinkedList<>();
private List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
BgpFlowSpecDetails flowSpecDetails = new BgpFlowSpecDetails(flowSpecComponents);
BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
List<BgpValueType> flowSpecComponents2 = new LinkedList<>();
private List<BgpFsOperatorValue> operatorValue2 = new ArrayList<>();
BgpFlowSpecDetails flowSpecDetails2 = new BgpFlowSpecDetails(flowSpecComponents2);
BgpFlowSpecNlri flowSpecDetails2 = new BgpFlowSpecNlri(flowSpecComponents2);
BgpFsPortNum portNum2 = new BgpFsPortNum(operatorValue2);
@Test
......
......@@ -16,23 +16,18 @@
package org.onosproject.bgpio.protocol.flowspec;
import org.junit.Test;
import org.onlab.packet.IpPrefix;
import com.google.common.testing.EqualsTester;
/**
* Test for BgpFsDestinationPrefix flow specification component.
*/
public class BgpFlowSpecPrefixTest {
private IpPrefix destinationPrefix1 = IpPrefix.valueOf("21.21.21.21/16");
private IpPrefix sourcePrefix1 = IpPrefix.valueOf("11.11.11.11/16");
private IpPrefix destinationPrefix2 = IpPrefix.valueOf("42.42.42.42/16");
private IpPrefix sourcePrefix2 = IpPrefix.valueOf("32.32.32.32/16");
private String routeKey1 = "flowRoute1";
private String routeKey2 = "flowRoute2";
private final BgpFlowSpecPrefix tlv1 = new BgpFlowSpecPrefix(destinationPrefix1, sourcePrefix1);
private final BgpFlowSpecPrefix sameAsTlv1 = new BgpFlowSpecPrefix(destinationPrefix1, sourcePrefix1);
private final BgpFlowSpecPrefix tlv2 = new BgpFlowSpecPrefix(destinationPrefix2, sourcePrefix2);
private final BgpFlowSpecRouteKey tlv1 = new BgpFlowSpecRouteKey(routeKey1);
private final BgpFlowSpecRouteKey sameAsTlv1 = new BgpFlowSpecRouteKey(routeKey1);
private final BgpFlowSpecRouteKey tlv2 = new BgpFlowSpecRouteKey(routeKey2);
@Test
public void testEquality() {
......
/*
* 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.protocol.flowspec;
import org.junit.Test;
import com.google.common.testing.EqualsTester;
/**
* Test for BgpFlowSpecRouteKeyTest flow specification component.
*/
public class BgpFlowSpecRouteKeyTest {
private static String routeKey1 = "flowRoute1";
private static String routeKey2 = "flowRoute2";
private final BgpFlowSpecRouteKey tlv1 = new BgpFlowSpecRouteKey(routeKey1);
private final BgpFlowSpecRouteKey sameAsTlv1 = new BgpFlowSpecRouteKey(routeKey1);
private final BgpFlowSpecRouteKey tlv2 = new BgpFlowSpecRouteKey(routeKey2);
@Test
public void testEquality() {
new EqualsTester()
.addEqualityGroup(tlv1, sameAsTlv1)
.addEqualityGroup(tlv2)
.testEquals();
}
}
......@@ -133,29 +133,23 @@ public class BgpControllerImpl implements BgpController {
}
Iterator<BgpValueType> listIterator = pathAttr.iterator();
boolean isLinkstate = false;
boolean isFlowSpec = false;
while (listIterator.hasNext()) {
BgpValueType attr = listIterator.next();
if (attr instanceof MpReachNlri) {
MpReachNlri mpReach = (MpReachNlri) attr;
if (mpReach.bgpFlowSpecInfo() == null) {
if (mpReach.bgpFlowSpecNlri() == null) {
isLinkstate = true;
} else {
isFlowSpec = true;
}
} else if (attr instanceof MpUnReachNlri) {
MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
if (mpUnReach.bgpFlowSpecInfo() == null) {
if (mpUnReach.bgpFlowSpecNlri() == null) {
isLinkstate = true;
} else {
isFlowSpec = true;
}
}
}
if (isLinkstate) {
peer.buildAdjRibIn(pathAttr);
} else if (isFlowSpec) {
peer.buildFlowSpecRib(pathAttr);
}
break;
default:
......
/*
* 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.bgp.controller.impl;
import java.util.Map;
import java.util.TreeMap;
import org.onosproject.bgpio.types.RouteDistinguisher;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
import com.google.common.base.MoreObjects;
/**
* Implementation of BGP flow specification RIB.
*/
public class BgpFlowSpecRib {
private Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> flowSpecTree = new TreeMap<>();
private Map<RouteDistinguisher, Map<BgpFlowSpecPrefix, BgpFlowSpecDetails>> vpnFlowSpecTree = new TreeMap<>();
/**
* Returns the BGP flow spec info.
*
* @return BGP flow spec tree
*/
public Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> flowSpecTree() {
return flowSpecTree;
}
/**
* Gets VPN flowspec tree.
*
* @return vpn flow spec tree
*/
public Map<RouteDistinguisher, Map<BgpFlowSpecPrefix, BgpFlowSpecDetails>> vpnFlowSpecTree() {
return vpnFlowSpecTree;
}
/**
* Update BGP flow spec details.
*
* @param prefix prefix Info
* @param flowSpec BGP flow specifications details
*/
public void add(BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
if (flowSpecTree.containsKey(prefix)) {
flowSpecTree.replace(prefix, flowSpec);
} else {
flowSpecTree.put(prefix, flowSpec);
}
}
/**
* Removes flow spec.
*
* @param flowSpec BGP flow specification
*/
public void delete(BgpFlowSpecPrefix flowSpec) {
if (flowSpecTree.containsKey(flowSpec)) {
flowSpecTree.remove(flowSpec);
}
}
/**
* Update BGP flow spec details with routedistinguisher.
*
* @param routeDistinguisher route distinguisher
* @param prefix prefix Info
* @param flowSpec BGP flow specifications details
*/
public void add(RouteDistinguisher routeDistinguisher, BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree;
if (!vpnFlowSpecTree.containsKey(routeDistinguisher)) {
fsTree = new TreeMap<>();
vpnFlowSpecTree.put(routeDistinguisher, fsTree);
} else {
fsTree = vpnFlowSpecTree().get(routeDistinguisher);
}
if (fsTree.containsKey(prefix)) {
fsTree.replace(prefix, flowSpec);
} else {
fsTree.put(prefix, flowSpec);
}
}
/**
* Removes flow spec.
*
* @param routeDistinguisher route distinguisher
* @param flowSpecPrefix BGP flow specification prefix
*/
public void delete(RouteDistinguisher routeDistinguisher, BgpFlowSpecPrefix flowSpecPrefix) {
if (vpnFlowSpecTree.containsKey(routeDistinguisher)) {
Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree = vpnFlowSpecTree().get(routeDistinguisher);
fsTree.remove(flowSpecPrefix);
if (fsTree.size() == 0) {
vpnFlowSpecTree.remove(routeDistinguisher);
}
}
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.omitNullValues()
.add("flowSpecTree", flowSpecTree)
.add("vpnFlowSpecTree", vpnFlowSpecTree)
.toString();
}
}
......@@ -19,14 +19,8 @@ package org.onosproject.bgp.controller.impl;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import org.jboss.netty.channel.Channel;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.bgp.controller.BgpController;
import org.onosproject.bgp.controller.BgpLocalRib;
import org.onosproject.bgp.controller.BgpPeer;
......@@ -36,8 +30,8 @@ import org.onosproject.bgpio.protocol.BgpFactories;
import org.onosproject.bgpio.protocol.BgpFactory;
import org.onosproject.bgpio.protocol.BgpLSNlri;
import org.onosproject.bgpio.protocol.BgpMessage;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecRouteKey;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
......@@ -45,8 +39,6 @@ import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
import org.onosproject.bgpio.types.AsPath;
import org.onosproject.bgpio.types.As4Path;
import org.onosproject.bgpio.types.BgpExtendedCommunity;
import org.onosproject.bgpio.types.BgpFsDestinationPrefix;
import org.onosproject.bgpio.types.BgpFsSourcePrefix;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.LocalPref;
import org.onosproject.bgpio.types.Med;
......@@ -54,14 +46,17 @@ import org.onosproject.bgpio.types.MpReachNlri;
import org.onosproject.bgpio.types.MpUnReachNlri;
import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.types.Origin;
import org.onosproject.bgpio.types.RouteDistinguisher;
import org.onosproject.bgpio.types.attr.WideCommunity;
import org.onosproject.bgpio.types.RpdCapabilityTlv;
import org.onosproject.bgpio.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.RejectedExecutionException;
......@@ -86,26 +81,6 @@ public class BgpPeerImpl implements BgpPeer {
private BgpLocalRib bgplocalRibVpn;
private AdjRibIn adjRib;
private VpnAdjRibIn vpnAdjRib;
private BgpFlowSpecRib flowSpecRibOut;
private BgpFlowSpecRib flowSpecRibIn;
/**
* Returns the flowSpec RIB out.
*
* @return flow Specification RIB out
*/
public BgpFlowSpecRib flowSpecRibOut() {
return flowSpecRibOut;
}
/**
* Returns the flowSpec RIB-in.
*
* @return flow Specification RIB-in
*/
public BgpFlowSpecRib flowSpecRibIn() {
return flowSpecRibIn;
}
/**
* Return the adjacency RIB-IN.
......@@ -145,8 +120,6 @@ public class BgpPeerImpl implements BgpPeer {
this.bgplocalRibVpn = bgpController.bgpLocalRibVpn();
this.adjRib = new AdjRibIn();
this.vpnAdjRib = new VpnAdjRibIn();
this.flowSpecRibOut = new BgpFlowSpecRib();
this.flowSpecRibIn = new BgpFlowSpecRib();
}
/**
......@@ -171,6 +144,11 @@ public class BgpPeerImpl implements BgpPeer {
if ((temp.getAfi() == afi) && (temp.getSafi() == sAfi)) {
return true;
}
} else if (tlv.getType() == RpdCapabilityTlv.TYPE) {
RpdCapabilityTlv temp = (RpdCapabilityTlv) tlv;
if ((temp.getAfi() == afi) && (temp.getSafi() == sAfi)) {
return true;
}
}
}
}
......@@ -182,12 +160,14 @@ public class BgpPeerImpl implements BgpPeer {
*
* @param operType operation type
* @param flowSpec flow specification details
* @param wideCommunity for route policy
*/
public final void sendFlowSpecUpdateMessageToPeer(FlowSpecOperation operType, BgpFlowSpecDetails flowSpec) {
public final void sendFlowSpecUpdateMessageToPeer(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity) {
List<BgpValueType> attributesList = new LinkedList<>();
byte sessionType = sessionInfo.isIbgpSession() ? (byte) 0 : (byte) 1;
byte sAfi = Constants.SAFI_FLOWSPEC_VALUE;
byte sAfi = Constants.VPN_SAFI_FLOWSPEC_VALUE;
boolean isFsCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
Constants.AFI_FLOWSPEC_VALUE,
......@@ -196,16 +176,26 @@ public class BgpPeerImpl implements BgpPeer {
boolean isVpnFsCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
Constants.AFI_FLOWSPEC_VALUE,
Constants.VPN_SAFI_FLOWSPEC_VALUE);
if ((!isFsCapabilitySet) && (!isVpnFsCapabilitySet)) {
boolean isRpdCapabilitySet = isCapabilitySupported(RpdCapabilityTlv.TYPE,
Constants.AFI_FLOWSPEC_RPD_VALUE,
Constants.SAFI_FLOWSPEC_RPD_VALUE);
boolean isVpnRpdCapabilitySet = isCapabilitySupported(RpdCapabilityTlv.TYPE,
Constants.AFI_FLOWSPEC_RPD_VALUE,
Constants.VPN_SAFI_FLOWSPEC_RDP_VALUE);
if ((!isFsCapabilitySet) && (!isVpnFsCapabilitySet) && (!isRpdCapabilitySet) && (!isVpnRpdCapabilitySet)) {
log.debug("Peer do not support BGP flow spec capability", channel.getRemoteAddress());
return;
}
if (isVpnFsCapabilitySet) {
if ((wideCommunity != null) && (isVpnRpdCapabilitySet)) {
sAfi = Constants.VPN_SAFI_FLOWSPEC_RDP_VALUE;
} else if (isVpnFsCapabilitySet) {
sAfi = Constants.VPN_SAFI_FLOWSPEC_VALUE;
}
attributesList.add(new Origin(sessionType));
attributesList.add(new Origin((byte) 0));
if (sessionType != 0) {
// EBGP
......@@ -232,6 +222,7 @@ public class BgpPeerImpl implements BgpPeer {
}
attributesList.add(new BgpExtendedCommunity(flowSpec.fsActionTlv()));
attributesList.add(wideCommunity);
if (operType == FlowSpecOperation.ADD) {
attributesList.add(new MpReachNlri(flowSpec, Constants.AFI_FLOWSPEC_VALUE, sAfi));
......@@ -247,38 +238,14 @@ public class BgpPeerImpl implements BgpPeer {
}
@Override
public void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
public void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity) {
Preconditions.checkNotNull(operType, "flow specification operation type cannot be null");
Preconditions.checkNotNull(prefix, "flow specification prefix cannot be null");
Preconditions.checkNotNull(routeKey, "flow specification prefix cannot be null");
Preconditions.checkNotNull(flowSpec, "flow specification details cannot be null");
Preconditions.checkNotNull(flowSpec.fsActionTlv(), "flow specification action cannot be null");
if (operType == FlowSpecOperation.ADD) {
if (flowSpec.routeDistinguisher() == null) {
if (flowSpecRibOut.flowSpecTree().containsKey(prefix)) {
sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE,
flowSpecRibOut.flowSpecTree().get(prefix));
}
flowSpecRibOut.add(prefix, flowSpec);
} else {
if (flowSpecRibOut.vpnFlowSpecTree().containsKey(flowSpec.routeDistinguisher())) {
Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree;
fsTree = flowSpecRibOut.vpnFlowSpecTree().get(flowSpec.routeDistinguisher());
if (fsTree.containsKey(prefix)) {
sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE,
fsTree.get(prefix));
}
}
flowSpecRibOut.add(flowSpec.routeDistinguisher(), prefix, flowSpec);
}
} else if (operType == FlowSpecOperation.DELETE) {
if (flowSpec.routeDistinguisher() == null) {
flowSpecRibOut.delete(prefix);
} else {
flowSpecRibOut.delete(flowSpec.routeDistinguisher(), prefix);
}
}
sendFlowSpecUpdateMessageToPeer(operType, flowSpec);
sendFlowSpecUpdateMessageToPeer(operType, routeKey, flowSpec, wideCommunity);
}
@Override
......@@ -297,65 +264,6 @@ public class BgpPeerImpl implements BgpPeer {
}
}
@Override
public void buildFlowSpecRib(List<BgpValueType> pathAttr) throws BgpParseException {
ListIterator<BgpValueType> iterator = pathAttr.listIterator();
BgpFlowSpecDetails bgpFlowSpecDetails = new BgpFlowSpecDetails();
FlowSpecOperation operType = FlowSpecOperation.UPDATE;
while (iterator.hasNext()) {
BgpValueType attr = iterator.next();
if (attr instanceof MpReachNlri) {
MpReachNlri mpReach = (MpReachNlri) attr;
bgpFlowSpecDetails.setFlowSpecComponents(mpReach.bgpFlowSpecInfo().flowSpecComponents());
bgpFlowSpecDetails.setRouteDistinguiher(mpReach.bgpFlowSpecInfo().routeDistinguisher());
operType = FlowSpecOperation.ADD;
}
if (attr instanceof BgpExtendedCommunity) {
BgpExtendedCommunity extCommunity = (BgpExtendedCommunity) attr;
bgpFlowSpecDetails.setFsActionTlv(extCommunity.fsActionTlv());
}
if (attr instanceof MpUnReachNlri) {
MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
bgpFlowSpecDetails.setFlowSpecComponents(mpUnReach.bgpFlowSpecInfo().flowSpecComponents());
bgpFlowSpecDetails.setRouteDistinguiher(mpUnReach.bgpFlowSpecInfo().routeDistinguisher());
operType = FlowSpecOperation.DELETE;
}
}
iterator = bgpFlowSpecDetails.flowSpecComponents().listIterator();
IpPrefix destIpPrefix = null;
IpPrefix srcIpPrefix = null;
while (iterator.hasNext()) {
BgpValueType fsAttr = iterator.next();
if (fsAttr instanceof BgpFsDestinationPrefix) {
BgpFsDestinationPrefix destinationPrefix = (BgpFsDestinationPrefix) fsAttr;
destIpPrefix = destinationPrefix.ipPrefix();
}
if (fsAttr instanceof BgpFsSourcePrefix) {
BgpFsSourcePrefix sourcePrefix = (BgpFsSourcePrefix) fsAttr;
srcIpPrefix = sourcePrefix.ipPrefix();
}
}
BgpFlowSpecPrefix prefix = new BgpFlowSpecPrefix(destIpPrefix, srcIpPrefix);
if (operType == FlowSpecOperation.ADD) {
if (bgpFlowSpecDetails.routeDistinguisher() == null) {
flowSpecRibIn.add(prefix, bgpFlowSpecDetails);
} else {
flowSpecRibIn.add(bgpFlowSpecDetails.routeDistinguisher(), prefix, bgpFlowSpecDetails);
}
} else if (operType == FlowSpecOperation.DELETE) {
if (bgpFlowSpecDetails.routeDistinguisher() == null) {
flowSpecRibIn.delete(prefix);
} else {
flowSpecRibIn.delete(bgpFlowSpecDetails.routeDistinguisher(), prefix);
}
}
}
/**
* Updates NLRI identifier node in a tree separately based on afi and safi.
*
......@@ -490,46 +398,12 @@ public class BgpPeerImpl implements BgpPeer {
localRibVpn.localRibUpdate(vpnAdjacencyRib());
}
/**
* Update peer flow specification RIB on peer disconnect.
*/
public void updateFlowSpecOnPeerDisconnect() {
boolean isCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
Constants.AFI_FLOWSPEC_VALUE,
Constants.SAFI_FLOWSPEC_VALUE);
if (isCapabilitySet) {
Set<BgpFlowSpecPrefix> flowSpecKeys = flowSpecRibOut.flowSpecTree().keySet();
for (BgpFlowSpecPrefix key : flowSpecKeys) {
BgpFlowSpecDetails flowSpecDetails = flowSpecRibOut.flowSpecTree().get(key);
sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE, flowSpecDetails);
}
}
boolean isVpnCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
Constants.AFI_FLOWSPEC_VALUE,
Constants.VPN_SAFI_FLOWSPEC_VALUE);
if (isVpnCapabilitySet) {
Set<RouteDistinguisher> flowSpecKeys = flowSpecRibOut.vpnFlowSpecTree().keySet();
for (RouteDistinguisher key : flowSpecKeys) {
Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree = flowSpecRibOut.vpnFlowSpecTree().get(key);
Set<BgpFlowSpecPrefix> fsKeys = fsTree.keySet();
for (BgpFlowSpecPrefix fsKey : fsKeys) {
BgpFlowSpecDetails flowSpecDetails = flowSpecRibOut.flowSpecTree().get(fsKey);
sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE, flowSpecDetails);
}
}
}
}
// ************************
// Channel related
// ************************
@Override
public final void disconnectPeer() {
this.updateFlowSpecOnPeerDisconnect();
this.channel.close();
}
......
/*
* 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.controller.impl;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.bgp.controller.impl.BgpFlowSpecRib;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
import org.onosproject.bgpio.types.BgpFsOperatorValue;
import org.onosproject.bgpio.types.BgpFsPortNum;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.RouteDistinguisher;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
/**
* Test cases for BGP Selection Algorithm.
*/
public class BgpFlowSpecRibTest {
/**
* Add flow specification to rib.
*/
@Test
public void bgpFlowSpecRibTests1() {
List<BgpValueType> flowSpecComponents = new LinkedList<>();
List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
BgpFlowSpecRib rib = new BgpFlowSpecRib();
IpPrefix destinationPrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.1"), 32);
IpPrefix sourcePrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.2"), 32);
BgpFlowSpecPrefix prefix = new BgpFlowSpecPrefix(destinationPrefix, sourcePrefix);
byte[] port = new byte[] {(byte) 0x1 };
operatorValue.add(new BgpFsOperatorValue((byte) 0x81, port));
BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
flowSpecComponents.add(portNum);
BgpFlowSpecDetails flowSpec = new BgpFlowSpecDetails(flowSpecComponents);
rib.add(prefix, flowSpec);
boolean isPresent = rib.flowSpecTree().containsKey(prefix);
assertThat(isPresent, is(true));
}
/**
* Add and delete flow specification to rib.
*/
@Test
public void bgpFlowSpecRibTest2() {
List<BgpValueType> flowSpecComponents = new LinkedList<>();
List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
BgpFlowSpecRib rib = new BgpFlowSpecRib();
IpPrefix destinationPrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.1"), 32);
IpPrefix sourcePrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.2"), 32);
BgpFlowSpecPrefix prefix = new BgpFlowSpecPrefix(destinationPrefix, sourcePrefix);
byte[] port = new byte[] {(byte) 0x1 };
operatorValue.add(new BgpFsOperatorValue((byte) 0x81, port));
BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
flowSpecComponents.add(portNum);
BgpFlowSpecDetails flowSpec = new BgpFlowSpecDetails(flowSpecComponents);
rib.add(prefix, flowSpec);
boolean isPresent = rib.flowSpecTree().containsKey(prefix);
assertThat(isPresent, is(true));
rib.delete(prefix);
isPresent = rib.flowSpecTree().containsKey(prefix);
assertThat(isPresent, is(false));
}
/**
* Add and delete flow specification with a specific VPN to rib.
*/
@Test
public void bgpFlowSpecRibTest3() {
List<BgpValueType> flowSpecComponents = new LinkedList<>();
List<BgpFsOperatorValue> operatorValue = new ArrayList<>();
RouteDistinguisher routeDistinguisher = new RouteDistinguisher(1);
BgpFlowSpecRib rib = new BgpFlowSpecRib();
IpPrefix destinationPrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.1"), 32);
IpPrefix sourcePrefix = IpPrefix.valueOf(IpAddress.valueOf("10.0.1.2"), 32);
BgpFlowSpecPrefix prefix = new BgpFlowSpecPrefix(destinationPrefix, sourcePrefix);
byte[] port = new byte[] {(byte) 0x1 };
operatorValue.add(new BgpFsOperatorValue((byte) 0x81, port));
BgpFsPortNum portNum = new BgpFsPortNum(operatorValue);
flowSpecComponents.add(portNum);
BgpFlowSpecDetails flowSpec = new BgpFlowSpecDetails(flowSpecComponents);
rib.add(routeDistinguisher, prefix, flowSpec);
boolean isPresent = rib.vpnFlowSpecTree().containsKey(routeDistinguisher);
assertThat(isPresent, is(true));
rib.delete(routeDistinguisher, prefix);
isPresent = rib.vpnFlowSpecTree().containsKey(routeDistinguisher);
assertThat(isPresent, is(false));
}
}