Jonathan Hart

Port the BGP implementation of SDN-IP.

......@@ -126,6 +126,8 @@ public class Router implements RouteListener {
bgpIntentsSynchronizerExecutor = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder()
.setNameFormat("bgp-intents-synchronizer-%d").build());
this.hostService.addListener(new InternalHostListener());
}
/**
......
......@@ -10,6 +10,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.sdnip.RouteUpdate.Type;
import org.onlab.onos.sdnip.bgp.BgpSessionManager;
import org.onlab.onos.sdnip.config.SdnIpConfigReader;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
......@@ -32,6 +33,7 @@ public class SdnIp {
private SdnIpConfigReader config;
private PeerConnectivity peerConnectivity;
private Router router;
private BgpSessionManager bgpSessionManager;
@Activate
protected void activate() {
......@@ -48,6 +50,9 @@ public class SdnIp {
router = new Router(intentService, hostService, config, interfaceService);
router.start();
bgpSessionManager = new BgpSessionManager(router);
bgpSessionManager.startUp(2000); // TODO
// TODO need to disable link discovery on external ports
router.update(new RouteUpdate(Type.UPDATE, new RouteEntry(
......
package org.onlab.onos.sdnip.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.onlab.onos.sdnip.bgp.BgpConstants.Notifications.MessageHeaderError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class for handling the decoding of the BGP messages.
*/
class BgpFrameDecoder extends FrameDecoder {
private static final Logger log =
LoggerFactory.getLogger(BgpFrameDecoder.class);
private final BgpSession bgpSession;
/**
* Constructor for a given BGP Session.
*
* @param bgpSession the BGP session state to use.
*/
BgpFrameDecoder(BgpSession bgpSession) {
this.bgpSession = bgpSession;
}
@Override
protected Object decode(ChannelHandlerContext ctx,
Channel channel,
ChannelBuffer buf) throws Exception {
//
// NOTE: If we close the channel during the decoding, we might still
// see some incoming messages while the channel closing is completed.
//
if (bgpSession.isClosed()) {
return null;
}
log.trace("BGP Peer: decode(): remoteAddr = {} localAddr = {} " +
"messageSize = {}",
ctx.getChannel().getRemoteAddress(),
ctx.getChannel().getLocalAddress(),
buf.readableBytes());
// Test for minimum length of the BGP message
if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
// No enough data received
return null;
}
//
// Mark the current buffer position in case we haven't received
// the whole message.
//
buf.markReaderIndex();
//
// Read and check the BGP message Marker field: it must be all ones
// (See RFC 4271, Section 4.1)
//
byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
buf.readBytes(marker);
for (int i = 0; i < marker.length; i++) {
if (marker[i] != (byte) 0xff) {
log.debug("BGP RX Error: invalid marker {} at position {}",
marker[i], i);
//
// ERROR: Connection Not Synchronized
//
// Send NOTIFICATION and close the connection
int errorCode = MessageHeaderError.ERROR_CODE;
int errorSubcode =
MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
ChannelBuffer txMessage =
bgpSession.prepareBgpNotification(errorCode, errorSubcode,
null);
ctx.getChannel().write(txMessage);
bgpSession.closeChannel(ctx);
return null;
}
}
//
// Read and check the BGP message Length field
//
int length = buf.readUnsignedShort();
if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
(length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
log.debug("BGP RX Error: invalid Length field {}. " +
"Must be between {} and {}",
length,
BgpConstants.BGP_HEADER_LENGTH,
BgpConstants.BGP_MESSAGE_MAX_LENGTH);
//
// ERROR: Bad Message Length
//
// Send NOTIFICATION and close the connection
ChannelBuffer txMessage =
bgpSession.prepareBgpNotificationBadMessageLength(length);
ctx.getChannel().write(txMessage);
bgpSession.closeChannel(ctx);
return null;
}
//
// Test whether the rest of the message is received:
// So far we have read the Marker (16 octets) and the
// Length (2 octets) fields.
//
int remainingMessageLen =
length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
if (buf.readableBytes() < remainingMessageLen) {
// No enough data received
buf.resetReaderIndex();
return null;
}
//
// Read the BGP message Type field, and process based on that type
//
int type = buf.readUnsignedByte();
remainingMessageLen--; // Adjust after reading the type
ChannelBuffer message = buf.readBytes(remainingMessageLen);
//
// Process the remaining of the message based on the message type
//
switch (type) {
case BgpConstants.BGP_TYPE_OPEN:
bgpSession.processBgpOpen(ctx, message);
break;
case BgpConstants.BGP_TYPE_UPDATE:
bgpSession.processBgpUpdate(ctx, message);
break;
case BgpConstants.BGP_TYPE_NOTIFICATION:
bgpSession.processBgpNotification(ctx, message);
break;
case BgpConstants.BGP_TYPE_KEEPALIVE:
bgpSession.processBgpKeepalive(ctx, message);
break;
default:
//
// ERROR: Bad Message Type
//
// Send NOTIFICATION and close the connection
int errorCode = MessageHeaderError.ERROR_CODE;
int errorSubcode = MessageHeaderError.BAD_MESSAGE_TYPE;
ChannelBuffer data = ChannelBuffers.buffer(1);
data.writeByte(type);
ChannelBuffer txMessage =
bgpSession.prepareBgpNotification(errorCode, errorSubcode,
data);
ctx.getChannel().write(txMessage);
bgpSession.closeChannel(ctx);
return null;
}
return null;
}
}
/**
* Implementation of the BGP protocol.
*/
package org.onlab.onos.sdnip.bgp;
\ No newline at end of file
......@@ -2,13 +2,15 @@ package org.onlab.packet;
import java.util.Arrays;
/**
* A class representing an IPv4 address.
* <p/>
* TODO this class is a clone of IpPrefix and still needs to be modified to
* look more like an IpAddress.
*/
public final class IpAddress {
public final class IpAddress implements Comparable<IpAddress> {
// TODO a comparator for netmasks? E.g. for sorting by prefix match order.
......@@ -289,6 +291,13 @@ public final class IpAddress {
}
@Override
public int compareTo(IpAddress o) {
Long lv = ((long) this.toRealInt()) & 0xffffffffL;
Long rv = ((long) o.toRealInt()) & 0xffffffffL;
return lv.compareTo(rv);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
......