Kunihiro Ishiguro

4 Octet AS Path Capability is sent to neighbor.

4 Octet AS in AS_PATH is parsed.
Now BGP can establish 4 Octet AS Path enabled peering with neighbor.

Change-Id: Ibb72e8037554928584ccafe6a14b82ffaca7e2cd
......@@ -227,6 +227,12 @@ public final class BgpConstants {
/** BGP UPDATE Attributes Type Code AS_PATH. */
public static final int TYPE = 2;
/** BGP AS length. */
public static final int AS_LENGTH = 2;
/** BGP 4 Octet AS length (RFC 6793). */
public static final int AS_4OCTET_LENGTH = 4;
/** BGP UPDATE AS_PATH Type: AS_SET. */
public static final int AS_SET = 1;
......
......@@ -23,6 +23,7 @@ import org.onosproject.sdnip.bgp.BgpConstants.Notifications;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.OpenMessageError;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.MultiprotocolExtensions;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.As4Octet;
import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -334,8 +335,14 @@ final class BgpOpen {
throw new BgpParseException(errorMsg);
}
long as4Number = message.readUnsignedInt();
// TODO: Implement support for 4-octet AS Numbers
bgpSession.setRemoteAs4OctetCapability();
bgpSession.setRemoteAs4Octet(as4Number);
// Copy remote 4-octet AS Number Capabilities and AS Number.
// This is temporary setting until local AS number configuration is supported.
bgpSession.setLocalAs4OctetCapability();
bgpSession.setRemoteAs(as4Number);
log.debug("BGP RX OPEN Capability: AS4 Number = {}",
as4Number);
break;
......@@ -420,6 +427,15 @@ final class BgpOpen {
message.writeByte(MultiprotocolExtensions.SAFI_MULTICAST);
}
// 4 octet AS path capability
if (bgpSession.getLocalAs4OctetCapability()) {
message.writeByte(Capabilities.TYPE); // Param type
message.writeByte(Capabilities.MIN_LENGTH +
As4Octet.LENGTH); // Param len
message.writeByte(As4Octet.CODE); // Capab, code
message.writeByte(As4Octet.LENGTH); // Capab, len
message.writeInt((int) bgpSession.getLocalAs());
}
return message;
}
}
......
......@@ -66,6 +66,7 @@ public class BgpSession extends SimpleChannelHandler {
private boolean remoteIpv4Multicast; // Peer IPv4/MULTICAST AFI/SAFI
private boolean remoteIpv6Unicast; // Peer IPv6/UNICAST AFI/SAFI
private boolean remoteIpv6Multicast; // Peer IPv6/MULTICAST AFI/SAFI
private boolean remoteAs4OctetCapability; // Peer 4 octet AS path capability
//
private SocketAddress localAddress; // Local IP addr/port
private Ip4Address localIp4Address; // Local IPv4 address
......@@ -77,6 +78,7 @@ public class BgpSession extends SimpleChannelHandler {
private boolean localIpv4Multicast; // Local IPv4/MULTICAST AFI/SAFI
private boolean localIpv6Unicast; // Local IPv6/UNICAST AFI/SAFI
private boolean localIpv6Multicast; // Local IPv6/MULTICAST AFI/SAFI
private boolean localAs4OctetCapability; // Local 4 octet AS path capability
//
private long localKeepaliveInterval; // Keepalive interval
......@@ -188,7 +190,7 @@ public class BgpSession extends SimpleChannelHandler {
// In the future the local AS number should be configured as part
// of an explicit BGP peering configuration.
//
this.localAs = remoteAs;
setLocalAs(remoteAs);
}
/**
......@@ -330,6 +332,47 @@ public class BgpSession extends SimpleChannelHandler {
}
/**
* Gets the BGP session remote 4 octet AS path capability.
*
* @return true when the BGP session remote has 4 octet AS path capability
*/
public boolean getRemoteAs4OctetCapability() {
return remoteAs4OctetCapability;
}
/**
* Sets the BGP session remote 4 octet AS path capability.
*/
void setRemoteAs4OctetCapability() {
this.remoteAs4OctetCapability = true;
}
/**
* Gets the BGP session local 4 octet AS path capability.
*
* @return true when the BGP session local has 4 octet AS path capability
*/
public boolean getLocalAs4OctetCapability() {
return localAs4OctetCapability;
}
/**
* Sets the BGP session local 4 octet AS path capability.
*/
void setLocalAs4OctetCapability() {
this.localAs4OctetCapability = true;
}
/**
* Gets the BGP session 4 octet AS path capability.
*
* @return true when the BGP session is 4 octet AS path capable
*/
public boolean isAs4OctetCapable() {
return getRemoteAs4OctetCapability() && getLocalAs4OctetCapability();
}
/**
* Gets the BGP session local address.
*
* @return the BGP session local address
......@@ -366,6 +409,15 @@ public class BgpSession extends SimpleChannelHandler {
}
/**
* Sets the BGP session local AS number.
*
* @param localAs the BGP session local AS number to set
*/
public void setLocalAs(long localAs) {
this.localAs = localAs;
}
/**
* Gets the BGP session local Holdtime.
*
* @return the BGP session local Holdtime
......
......@@ -26,6 +26,7 @@ import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onosproject.sdnip.bgp.BgpConstants.Update.AsPath;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.UpdateMessageError;
import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException;
import org.slf4j.Logger;
......@@ -610,17 +611,30 @@ final class BgpUpdate {
throw new BgpParseException(errorMsg);
}
// 4-octet AS number handling.
int asPathLen;
if (bgpSession.isAs4OctetCapable()) {
asPathLen = AsPath.AS_4OCTET_LENGTH;
} else {
asPathLen = AsPath.AS_LENGTH;
}
// Parse the AS numbers
if (2 * pathSegmentLength > attrLen) {
if (asPathLen * pathSegmentLength > attrLen) {
// ERROR: Malformed AS_PATH
actionsBgpUpdateMalformedAsPath(bgpSession, ctx);
String errorMsg = "Malformed AS Path";
throw new BgpParseException(errorMsg);
}
attrLen -= (2 * pathSegmentLength);
attrLen -= (asPathLen * pathSegmentLength);
ArrayList<Long> segmentAsNumbers = new ArrayList<>();
while (pathSegmentLength-- > 0) {
long asNumber = message.readUnsignedShort();
long asNumber;
if (asPathLen == AsPath.AS_4OCTET_LENGTH) {
asNumber = message.readUnsignedInt();
} else {
asNumber = message.readUnsignedShort();
}
segmentAsNumbers.add(asNumber);
}
......
......@@ -48,6 +48,8 @@ public class BgpNeighborsListCommand extends AbstractShellCommand {
" Local router ID %s, IP %s, BGP version %d, Hold time %d";
private static final String FORMAT_NEIGHBOR_LINE5 =
" Local AFI/SAFI IPv4 Unicast %s Multicast %s, IPv6 Unicast %s Multicast %s";
private static final String FORMAT_NEIGHBOR_LINE6 =
" 4 Octet AS Capability: %s %s";
@Override
protected void execute() {
......@@ -120,6 +122,11 @@ public class BgpNeighborsListCommand extends AbstractShellCommand {
bgpSession.getLocalIpv4Multicast() ? "YES" : "NO",
bgpSession.getLocalIpv6Unicast() ? "YES" : "NO",
bgpSession.getLocalIpv6Multicast() ? "YES" : "NO");
if (bgpSession.getLocalAs4OctetCapability() || bgpSession.getRemoteAs4OctetCapability()) {
print(FORMAT_NEIGHBOR_LINE6,
bgpSession.getLocalAs4OctetCapability() ? "Advertised" : "",
bgpSession.getRemoteAs4OctetCapability() ? "Received" : "");
}
}
/**
......