[ONOS-3857] BGP flow spec NLRI encoding for MP_REACH and MP_UNREACH.
Change-Id: I44237a12c4235fda2fcfafe60c3935159dae5231
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
index 2e4e659..49fc6a7 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
@@ -19,11 +19,14 @@
import java.net.InetAddress;
import java.util.LinkedList;
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.linkstate.BgpPrefixIPv4LSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
@@ -42,13 +45,15 @@
private static final Logger log = LoggerFactory.getLogger(MpReachNlri.class);
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;
/**
* Constructor to initialize parameters.
@@ -68,6 +73,16 @@
this.length = length;
}
+ public MpReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
+ this.mpReachNlri = null;
+ this.isMpReachNlri = true;
+ this.length = 0;
+ this.ipNextHop = null;
+ this.bgpFlowSpecInfo = bgpFlowSpecInfo;
+ this.afi = afi;
+ this.safi = safi;
+ }
+
/**
* Returns whether MpReachNlri is present.
*
@@ -96,6 +111,15 @@
}
/**
+ * Returns BGP flow specification info.
+ *
+ * @return BGP flow specification info
+ */
+ public BgpFlowSpecDetails bgpFlowSpecInfo() {
+ return this.bgpFlowSpecInfo;
+ }
+
+ /**
* Reads from ChannelBuffer and parses MpReachNlri.
*
* @param cb channelBuffer
@@ -161,6 +185,79 @@
}
mpReachNlri.add(bgpLSNlri);
}
+ } else if ((afi == Constants.AFI_FLOWSPEC_VALUE)
+ && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
+ || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+ List<BgpValueType> flowSpecComponents = new LinkedList<>();
+ BgpValueType flowSpecComponent = null;
+
+ byte nextHopLen = tempCb.readByte();
+ if (nextHopLen > 0) {
+ InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
+ if (ipAddress.isMulticastAddress()) {
+ throw new BgpParseException("Multicast not supported");
+ }
+ ipNextHop = Ip4Address.valueOf(ipAddress);
+ }
+
+ byte reserved = tempCb.readByte();
+ short totNlriLen = tempCb.getByte(tempCb.readerIndex());
+ if (totNlriLen >= FLOW_SPEC_LEN) {
+ totNlriLen = tempCb.readShort();
+ } else {
+ totNlriLen = tempCb.readByte();
+ }
+ if (tempCb.readableBytes() < totNlriLen) {
+ Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+ BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
+ }
+ tempBuf = tempCb.readBytes(totNlriLen);
+ while (tempBuf.readableBytes() > 0) {
+ short type = tempBuf.readByte();
+ switch (type) {
+ case Constants.BGP_FLOWSPEC_DST_PREFIX:
+ flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_SRC_PREFIX:
+ flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_IP_PROTO:
+ flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_PORT:
+ flowSpecComponent = BgpFsPortNum.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_DST_PORT:
+ flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_SRC_PORT:
+ flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_ICMP_TP:
+ flowSpecComponent = BgpFsIcmpType.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_ICMP_CD:
+ flowSpecComponent = BgpFsIcmpType.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_TCP_FLAGS:
+ flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_PCK_LEN:
+ flowSpecComponent = BgpFsPacketLength.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_DSCP:
+ flowSpecComponent = BgpFsDscpValue.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_FRAGMENT:
+ flowSpecComponent = BgpFsFragment.read(tempBuf);
+ break;
+ default:
+ log.debug("flow spec type not supported" + type);
+ break;
+ }
+ flowSpecComponents.add(flowSpecComponent);
+ }
+ return new MpReachNlri(new BgpFlowSpecDetails(flowSpecComponents), afi, safi);
} else {
throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
}
@@ -202,14 +299,114 @@
@Override
public int write(ChannelBuffer cb) {
- //Not to be Implemented as of now
- return 0;
+ int iLenStartIndex = cb.writerIndex();
+ if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
+ || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+
+ cb.writeByte(FLAGS);
+ cb.writeByte(MPREACHNLRI_TYPE);
+
+ int mpReachDataIndx = cb.writerIndex();
+ cb.writeShort(0);
+
+ cb.writeShort(afi);
+ cb.writeByte(safi);
+ //next hop address
+ cb.writeByte(0);
+ //sub network points of attachment
+ cb.writeByte(0);
+
+ if (bgpFlowSpecInfo.routeDistinguisher() != null) {
+ cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
+ }
+
+ ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
+ int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
+
+ List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
+ ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+
+ 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:
+ 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);
+ } else {
+ cb.writeByte(len);
+ }
+ //Copy from bynamic buffer to channel buffer
+ cb.writeBytes(flowSpecTmpBuff);
+
+ int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
+ cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
+
+ }
+
+ return cb.writerIndex() - iLenStartIndex;
}
@Override
public String toString() {
- return MoreObjects.toStringHelper(getClass())
+ return MoreObjects.toStringHelper(getClass()).omitNullValues()
.add("mpReachNlri", mpReachNlri)
+ .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
.add("afi", afi)
.add("safi", safi)
.add("ipNextHop", ipNextHop)
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
index f354b3e..0931773 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
@@ -18,10 +18,13 @@
import java.util.LinkedList;
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.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
@@ -40,12 +43,14 @@
private static final Logger log = LoggerFactory.getLogger(MpUnReachNlri.class);
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;
/**
* Constructor to initialize parameters.
@@ -64,6 +69,24 @@
this.length = length;
}
+ public MpUnReachNlri(BgpFlowSpecDetails bgpFlowSpecInfo, short afi, byte safi) {
+ this.mpUnReachNlri = null;
+ this.isMpUnReachNlri = true;
+ this.length = 0;
+ this.bgpFlowSpecInfo = bgpFlowSpecInfo;
+ this.afi = afi;
+ this.safi = safi;
+ }
+
+ /**
+ * Returns BGP flow specification info.
+ *
+ * @return BGP flow specification info
+ */
+ public BgpFlowSpecDetails bgpFlowSpecInfo() {
+ return this.bgpFlowSpecInfo;
+ }
+
/**
* Reads from ChannelBuffer and parses MpUnReachNlri.
*
@@ -123,13 +146,76 @@
break;
default:
log.debug("nlriType not supported" + nlriType);
+ break;
}
mpUnReachNlri.add(bgpLSNlri);
}
+ } else if ((afi == Constants.AFI_FLOWSPEC_VALUE)
+ && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
+ || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+ List<BgpValueType> flowSpecComponents = new LinkedList<>();
+ BgpValueType flowSpecComponent = null;
+
+ short totNlriLen = tempCb.getByte(tempCb.readerIndex());
+ if (totNlriLen >= FLOW_SPEC_LEN) {
+ totNlriLen = tempCb.readShort();
+ } else {
+ totNlriLen = tempCb.readByte();
+ }
+ if (tempCb.readableBytes() < totNlriLen) {
+ Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
+ BgpErrorType.ATTRIBUTE_LENGTH_ERROR, totNlriLen);
+ }
+ tempBuf = tempCb.readBytes(totNlriLen);
+ while (tempBuf.readableBytes() > 0) {
+ short type = tempBuf.readByte();
+ switch (type) {
+ case Constants.BGP_FLOWSPEC_DST_PREFIX:
+ flowSpecComponent = BgpFsDestinationPrefix.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_SRC_PREFIX:
+ flowSpecComponent = BgpFsSourcePrefix.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_IP_PROTO:
+ flowSpecComponent = BgpFsIpProtocol.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_PORT:
+ flowSpecComponent = BgpFsPortNum.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_DST_PORT:
+ flowSpecComponent = BgpFsDestinationPortNum.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_SRC_PORT:
+ flowSpecComponent = BgpFsSourcePortNum.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_ICMP_TP:
+ flowSpecComponent = BgpFsIcmpType.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_ICMP_CD:
+ flowSpecComponent = BgpFsIcmpType.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_TCP_FLAGS:
+ flowSpecComponent = BgpFsTcpFlags.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_PCK_LEN:
+ flowSpecComponent = BgpFsPacketLength.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_DSCP:
+ flowSpecComponent = BgpFsDscpValue.read(tempBuf);
+ break;
+ case Constants.BGP_FLOWSPEC_FRAGMENT:
+ flowSpecComponent = BgpFsFragment.read(tempBuf);
+ break;
+ default:
+ log.debug("flow spec type not supported" + type);
+ break;
+ }
+ flowSpecComponents.add(flowSpecComponent);
+ }
+ return new MpUnReachNlri(new BgpFlowSpecDetails(flowSpecComponents), afi, safi);
} else {
//TODO: check with the values got from capability
- throw new BgpParseException("Not Supporting afi " + afi
- + "safi " + safi);
+ throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
}
}
return new MpUnReachNlri(mpUnReachNlri, afi, safi,
@@ -188,8 +274,97 @@
@Override
public int write(ChannelBuffer cb) {
- //Not to be Implemented as of now
- return 0;
+ int iLenStartIndex = cb.writerIndex();
+ if ((afi == Constants.AFI_FLOWSPEC_VALUE) && ((safi == Constants.SAFI_FLOWSPEC_VALUE) ||
+ (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+
+ cb.writeByte(FLAGS);
+ cb.writeByte(MPUNREACHNLRI_TYPE);
+
+ int mpUnReachIndx = cb.writerIndex();
+ cb.writeShort(0);
+
+ cb.writeShort(afi);
+ cb.writeByte(safi);
+
+ if (bgpFlowSpecInfo.routeDistinguisher() != null) {
+ cb.writeLong(bgpFlowSpecInfo.routeDistinguisher().getRouteDistinguisher());
+ }
+
+ ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
+ int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();
+
+ List<BgpValueType> flowSpec = bgpFlowSpecInfo.flowSpecComponents();
+ ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
+ 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:
+ }
+ }
+
+ 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);
+
+ int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
+ cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
+ }
+
+ return cb.writerIndex() - iLenStartIndex;
}
@Override
@@ -200,8 +375,9 @@
@Override
public String toString() {
- return MoreObjects.toStringHelper(getClass())
+ return MoreObjects.toStringHelper(getClass()).omitNullValues()
.add("mpReachNlri", mpUnReachNlri)
+ .add("bgpFlowSpecInfo", bgpFlowSpecInfo)
.add("afi", afi)
.add("safi", safi)
.add("length", length)