[ONOS-8036] BGP-LS has only partial support for IPv6
- Removed hard-coded Ipv4Address and replaced with the generic
IpAddress wherever necessary
- Added support of AFI = 2 (IPv6) in MPReachNlri and MPUnreachNlri
- Added a new config parameter for IPv6 in BGP Config. This allows
AFI = 2 to be sent in BGP Open messages
- Skipped TLV 1170 and 1173, which were causing exceptions
Change-Id: I76e69021b1d2687754bbf700681070051e347942
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java
index 4346b86..aaddc6d 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java
@@ -158,6 +158,24 @@
*/
Builder setEvpnCapabilityTlv(boolean isEvpnCapabilitySet);
+ /**
+ * Sets if the BGP connection uses IPv4 Unicast connections.
+ *
+ * @param ipV4UnicastCapabilityTlvSet boolean value to know if IPv4 is used
+ *
+ * @return Builder by setting capabilities
+ */
+ Builder setIpV4UnicastCapabilityTlvSet(boolean ipV4UnicastCapabilityTlvSet);
+
+ /**
+ * Sets if the BGP connection uses IPv6 Unicast connections.
+ *
+ * @param ipV6UnicastCapabilityTlvSet boolean value to know if IPv6 is used
+ *
+ * @return Builder by setting capabilities
+ */
+ Builder setIpV6UnicastCapabilityTlvSet(boolean ipV6UnicastCapabilityTlvSet);
+
@Override
Builder setHeader(BgpHeader bgpMsgHeader);
}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java
index 8ed830f..cb757e3 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java
@@ -56,6 +56,7 @@
private static final Logger log = LoggerFactory.getLogger(BgpPrefixIPv4LSNlriVer4.class);
public static final int PREFIX_IPV4_NLRITYPE = 3;
+ public static final int PREFIX_IPV6_NLRITYPE = 4;
public static final int IDENTIFIER_LENGTH = 16;
private long identifier;
private byte protocolId;
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java
index 61486ed..716101c 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java
@@ -319,6 +319,7 @@
private boolean isBgpIdSet = false;
private int bgpId;
private boolean isIpV4UnicastCapabilityTlvSet = true;
+ private boolean isIpV6UnicastCapabilityTlvSet = false;
private boolean isLargeAsCapabilityTlvSet = false;
private boolean isLsCapabilityTlvSet = false;
private boolean isFlowSpecCapabilityTlvSet = false;
@@ -344,7 +345,14 @@
if (this.isIpV4UnicastCapabilityTlvSet) {
BgpValueType tlv;
tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV4_UNICAST, RES,
- (byte) Constants.SAFI_IPV4_UNICAST);
+ (byte) Constants.SAFI_UNICAST);
+ this.capabilityTlv.add(tlv);
+ }
+
+ if (this.isIpV6UnicastCapabilityTlvSet) {
+ BgpValueType tlv;
+ tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV6_UNICAST, RES,
+ (byte) Constants.SAFI_UNICAST);
this.capabilityTlv.add(tlv);
}
@@ -460,6 +468,18 @@
this.isEvpnCapabilityTlvSet = isEvpnCapabilitySet;
return this;
}
+
+ @Override
+ public Builder setIpV4UnicastCapabilityTlvSet(boolean isIpV4UnicastCapabilityTlvSet) {
+ this.isIpV4UnicastCapabilityTlvSet = isIpV4UnicastCapabilityTlvSet;
+ return this;
+ }
+
+ @Override
+ public Builder setIpV6UnicastCapabilityTlvSet(boolean isIpV6UnicastCapabilityTlvSet) {
+ this.isIpV6UnicastCapabilityTlvSet = isIpV6UnicastCapabilityTlvSet;
+ return this;
+ }
}
@Override
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java
index 4c2bd67..0d58651 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java
@@ -89,6 +89,8 @@
public static final short ATTR_PREFIX_OSPF_FWD_ADDR = 1156;
public static final short ATTR_PREFIX_OPAQUE_ATTR = 1157;
+ public static final short ATTR_PREFIX_FLAGS = 1170;
+ public static final short ATTR_EXTENDED_ADMINISTRATIVE_GROUP = 1173;
public static final byte LINKSTATE_ATTRIB_TYPE = 29;
public static final byte TYPE_AND_LEN = 4;
private boolean isLinkStateAttribute = false;
@@ -279,9 +281,21 @@
bgpLSAttrib = BgpPrefixAttrOpaqueData.read(tempCb);
break;
+ case ATTR_PREFIX_FLAGS:
+ case ATTR_EXTENDED_ADMINISTRATIVE_GROUP:
+ //We are not using these bytes, but simply skipping them.
+ //If we don't skip but simply ignore these, the while loop
+ //reads wrong bytes and throws BgpParseException
+
+ //TODO : Use these bytes if required
+ int prefixFlagsLength = tempCb.readShort();
+ if (tempCb.readableBytes() > 0) {
+ tempCb.skipBytes(prefixFlagsLength);
+ }
+ break;
+
default:
- throw new BgpParseException(
- "The Bgp-LS Attribute is not supported : "
+ throw new BgpParseException("The Bgp-LS Attribute is not supported : "
+ tlvCodePoint);
}
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 578f4fe..0afb756 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
@@ -18,7 +18,7 @@
import com.google.common.base.MoreObjects;
import org.jboss.netty.buffer.ChannelBuffer;
-import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpEvpnNlri;
import org.onosproject.bgpio.protocol.BgpLSNlri;
@@ -38,6 +38,8 @@
import java.util.List;
import java.util.ListIterator;
+
+
/*
* Provides Implementation of MpReach Nlri BGP Path Attribute.
*/
@@ -52,9 +54,10 @@
private final int length;
private final short afi;
private final byte safi;
- private final Ip4Address ipNextHop;
+ private final IpAddress ipNextHop;
private BgpFlowSpecNlri bgpFlowSpecNlri;
private List<BgpEvpnNlri> evpnNlri;
+ public static final int ONE_BYTE_LENGTH = 8;
/**
* Constructor to initialize parameters.
@@ -65,7 +68,7 @@
* @param ipNextHop nexthop IpAddress
* @param length of MpReachNlri
*/
- public MpReachNlri(List<BgpLSNlri> mpReachNlri, short afi, byte safi, Ip4Address ipNextHop, int length) {
+ public MpReachNlri(List<BgpLSNlri> mpReachNlri, short afi, byte safi, IpAddress ipNextHop, int length) {
this.mpReachNlri = mpReachNlri;
this.isMpReachNlri = true;
this.ipNextHop = ipNextHop;
@@ -99,7 +102,7 @@
* @param safi safi
* @param ipNextHop IP Nexthop
*/
- public MpReachNlri(List<BgpEvpnNlri> evpnNlri, short afi, byte safi, Ip4Address ipNextHop) {
+ public MpReachNlri(List<BgpEvpnNlri> evpnNlri, short afi, byte safi, IpAddress ipNextHop) {
this.mpReachNlri = null;
this.length = 42;
this.ipNextHop = ipNextHop;
@@ -226,7 +229,7 @@
ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
short afi = 0;
byte safi = 0;
- Ip4Address ipNextHop = null;
+ IpAddress ipNextHop = null;
while (tempCb.readableBytes() > 0) {
afi = tempCb.readShort();
safi = tempCb.readByte();
@@ -239,7 +242,7 @@
if (ipAddress.isMulticastAddress()) {
throw new BgpParseException("Multicast not supported");
}
- ipNextHop = Ip4Address.valueOf(ipAddress);
+ ipNextHop = IpAddress.valueOf(ipAddress);
byte reserved = tempCb.readByte();
while (tempCb.readableBytes() > 0) {
@@ -258,6 +261,9 @@
bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
break;
case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
+ case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV6_NLRITYPE:
+ //RFC 7752 : Structure of IPv4 and IPv6 is same
+
bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, safi);
break;
default:
@@ -279,7 +285,7 @@
if (ipAddress.isMulticastAddress()) {
throw new BgpParseException("Multicast not supported");
}
- ipNextHop = Ip4Address.valueOf(ipAddress);
+ ipNextHop = IpAddress.valueOf(ipAddress);
}
byte reserved = tempCb.readByte();
@@ -360,12 +366,11 @@
List<BgpEvpnNlri> eVpnComponents = null;
byte nextHopLen = tempCb.readByte();
- InetAddress ipAddress = Validation.toInetAddress(nextHopLen,
- tempCb);
+ InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
if (ipAddress.isMulticastAddress()) {
throw new BgpParseException("Multicast not supported");
}
- ipNextHop = Ip4Address.valueOf(ipAddress);
+ ipNextHop = IpAddress.valueOf(ipAddress);
byte reserved = tempCb.readByte();
while (tempCb.readableBytes() > 0) {
BgpEvpnNlri eVpnComponent = BgpEvpnNlriImpl.read(tempCb);
@@ -377,6 +382,27 @@
return new MpReachNlri(eVpnComponents, afi, safi, ipNextHop);
+ } else if ((afi == Constants.AFI_IPV4_UNICAST && safi == Constants.SAFI_UNICAST)
+ || (afi == Constants.AFI_IPV6_UNICAST && safi == Constants.SAFI_UNICAST)) {
+ byte nextHopLen = tempCb.readByte();
+ InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
+ if (ipAddress.isMulticastAddress()) {
+ throw new BgpParseException("Multicast not supported");
+ }
+ ipNextHop = IpAddress.valueOf(ipAddress);
+ byte snpa = tempCb.readByte();
+
+ //Right now, we do not know where to use these bytes so we skip them
+ //If we do not skip, there are errors in reading subsequent TLVs
+
+ //TODO : Use this info, if required
+ if (tempCb.readableBytes() > 0) {
+ int mpReachNlriPrefixLength = tempCb.readByte() / ONE_BYTE_LENGTH; //Convert bits to bytes
+
+ tempCb.skipBytes(mpReachNlriPrefixLength);
+ }
+
+ return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength());
} else {
throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
}
@@ -403,7 +429,7 @@
*
* @return Nexthop IpAddress
*/
- public Ip4Address nexthop4() {
+ public IpAddress nexthop() {
return this.ipNextHop;
}
@@ -473,9 +499,15 @@
cb.writeShort(0);
cb.writeShort(afi);
cb.writeByte(safi);
- // ip address length
- cb.writeByte(0x04);
- cb.writeInt(ipNextHop.toInt());
+ // ip address length and then octets
+ byte[] ipnextHopOctets = ipNextHop.toOctets();
+ byte ipAddrLen = (byte) (ipnextHopOctets.length);
+ cb.writeByte(ipAddrLen);
+
+ for (int temp = 0; temp < ipAddrLen; temp++) {
+ cb.writeByte(ipnextHopOctets[temp]);
+ }
+
//sub network points of attachment
cb.writeByte(0);
@@ -527,4 +559,4 @@
// TODO Auto-generated method stub
return 0;
}
-}
\ No newline at end of file
+}
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 ac63ba7..1fb844c 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
@@ -219,6 +219,9 @@
bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
break;
case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
+ case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV6_NLRITYPE:
+ //RFC 7752 : Structure of IPv4 and IPv6 is same
+
bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi,
safi);
break;
@@ -317,6 +320,18 @@
}
return new MpUnReachNlri(eVpnComponents, afi, safi);
+ } else if ((afi == Constants.AFI_IPV4_UNICAST && safi == Constants.SAFI_UNICAST)
+ || (afi == Constants.AFI_IPV6_UNICAST && safi == Constants.SAFI_UNICAST)) {
+ //Right now, we do not know where to use these bytes so we skip them
+ //If we do not skip, there are errors in reading subsequent TLVs
+
+ //TODO : Use this info, if required
+ int remainingLen = parseFlags.getLength() - 3; //Short for AFI, byte for SAFI
+
+ if (remainingLen > 0) {
+ tempCb.skipBytes(remainingLen);
+ }
+
} else {
//TODO: check with the values got from capability
throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
@@ -477,4 +492,4 @@
.add("length", length)
.toString();
}
-}
\ No newline at end of file
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java
index 1839a31..4b6c6eb 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java
@@ -35,7 +35,8 @@
public static final byte VPN_SAFI_VALUE = (byte) 0x80;
public static final byte SAFI_VALUE = 71;
public static final short AFI_IPV4_UNICAST = 1;
- public static final byte SAFI_IPV4_UNICAST = 1;
+ public static final short AFI_IPV6_UNICAST = 2;
+ public static final byte SAFI_UNICAST = 1;
public static final short AFI_FLOWSPEC_VALUE = 1;
public static final byte SAFI_FLOWSPEC_VALUE = (byte) 133;
public static final byte VPN_SAFI_FLOWSPEC_VALUE = (byte) 134;
@@ -92,4 +93,4 @@
public static final byte BGP_FLOW_SPEC_LEN_MASK = 0x30;
public static final byte BGP_FLOW_SPEC_END_OF_LIST_MASK = (byte) 0x80;
-}
\ No newline at end of file
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
index 3764842..21ab244 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
@@ -41,6 +41,9 @@
public static final byte THIRD_BIT = 0x20;
public static final byte FOURTH_BIT = (byte) 0x10;
public static final byte IPV4_SIZE = 4;
+ public static final byte IPV6_SIZE = 16;
+ public static final int INET4_LENGTH = 32;
+
private boolean firstBit;
private boolean secondBit;
private boolean thirdBit;
@@ -227,10 +230,20 @@
* @return object of IpPrefix
*/
public static IpPrefix bytesToPrefix(byte[] value, int length) {
- if (value.length != IPV4_SIZE) {
- value = Arrays.copyOf(value, IPV4_SIZE);
+ if (length <= INET4_LENGTH) {
+ //Treat like IPv4 address
+ if (value.length != IPV4_SIZE) {
+ value = Arrays.copyOf(value, IPV4_SIZE);
+ }
+ IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length);
+ return ipPrefix;
+ } else {
+ //Treat this like IPv6 address
+ if (value.length != IPV6_SIZE) {
+ value = Arrays.copyOf(value, IPV6_SIZE);
+ }
+ IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET6, value, length);
+ return ipPrefix;
}
- IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length);
- return ipPrefix;
}
}