Ported BGP tests from old codebase
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerChannelHandler.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerChannelHandler.java
new file mode 100644
index 0000000..1b51d52
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/TestBgpPeerChannelHandler.java
@@ -0,0 +1,250 @@
+package org.onlab.onos.sdnip.bgp;
+
+import java.util.Collection;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.SimpleChannelHandler;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+/**
+ * Class for handling the remote BGP Peer session.
+ */
+class TestBgpPeerChannelHandler extends SimpleChannelHandler {
+ static final long PEER_AS = 65001;
+ static final int PEER_HOLDTIME = 120; // 120 seconds
+ final IpAddress bgpId; // The BGP ID
+ final long localPref; // Local preference for routes
+ final long multiExitDisc = 20; // MED value
+
+ ChannelHandlerContext savedCtx;
+
+ /**
+ * Constructor for given BGP ID.
+ *
+ * @param bgpId the BGP ID to use
+ * @param localPref the local preference for the routes to use
+ */
+ TestBgpPeerChannelHandler(IpAddress bgpId,
+ long localPref) {
+ this.bgpId = bgpId;
+ this.localPref = localPref;
+ }
+
+ /**
+ * Closes the channel.
+ */
+ void closeChannel() {
+ savedCtx.getChannel().close();
+ }
+
+ @Override
+ public void channelConnected(ChannelHandlerContext ctx,
+ ChannelStateEvent channelEvent) {
+ this.savedCtx = ctx;
+ // Prepare and transmit BGP OPEN message
+ ChannelBuffer message = prepareBgpOpen();
+ ctx.getChannel().write(message);
+
+ // Prepare and transmit BGP KEEPALIVE message
+ message = prepareBgpKeepalive();
+ ctx.getChannel().write(message);
+ }
+
+ @Override
+ public void channelDisconnected(ChannelHandlerContext ctx,
+ ChannelStateEvent channelEvent) {
+ // Nothing to do
+ }
+
+ /**
+ * Prepares BGP OPEN message.
+ *
+ * @return the message to transmit (BGP header included)
+ */
+ ChannelBuffer prepareBgpOpen() {
+ ChannelBuffer message =
+ ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+ message.writeByte(BgpConstants.BGP_VERSION);
+ message.writeShort((int) PEER_AS);
+ message.writeShort(PEER_HOLDTIME);
+ message.writeInt(bgpId.toInt());
+ message.writeByte(0); // No Optional Parameters
+ return prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN, message);
+ }
+
+ /**
+ * Prepares BGP UPDATE message.
+ *
+ * @param nextHopRouter the next-hop router address for the routes to add
+ * @param addedRoutes the routes to add
+ * @param withdrawnRoutes the routes to withdraw
+ * @return the message to transmit (BGP header included)
+ */
+ ChannelBuffer prepareBgpUpdate(IpAddress nextHopRouter,
+ Collection<IpPrefix> addedRoutes,
+ Collection<IpPrefix> withdrawnRoutes) {
+ int attrFlags;
+ ChannelBuffer message =
+ ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+ ChannelBuffer pathAttributes =
+ ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+
+ // Encode the Withdrawn Routes
+ ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
+ message.writeShort(encodedPrefixes.readableBytes());
+ message.writeBytes(encodedPrefixes);
+
+ // Encode the Path Attributes
+ // ORIGIN: IGP
+ attrFlags = 0x40; // Transitive flag
+ pathAttributes.writeByte(attrFlags);
+ pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
+ pathAttributes.writeByte(1); // Data length
+ pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
+ // AS_PATH: Two Path Segments of 3 ASes each
+ attrFlags = 0x40; // Transitive flag
+ pathAttributes.writeByte(attrFlags);
+ pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
+ pathAttributes.writeByte(16); // Data length
+ byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
+ pathAttributes.writeByte(pathSegmentType1);
+ pathAttributes.writeByte(3); // Three ASes
+ pathAttributes.writeShort(65010); // AS=65010
+ pathAttributes.writeShort(65020); // AS=65020
+ pathAttributes.writeShort(65030); // AS=65030
+ byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
+ pathAttributes.writeByte(pathSegmentType2);
+ pathAttributes.writeByte(3); // Three ASes
+ pathAttributes.writeShort(65041); // AS=65041
+ pathAttributes.writeShort(65042); // AS=65042
+ pathAttributes.writeShort(65043); // AS=65043
+ // NEXT_HOP: nextHopRouter
+ attrFlags = 0x40; // Transitive flag
+ pathAttributes.writeByte(attrFlags);
+ pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
+ pathAttributes.writeByte(4); // Data length
+ pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
+ // LOCAL_PREF: localPref
+ attrFlags = 0x40; // Transitive flag
+ pathAttributes.writeByte(attrFlags);
+ pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
+ pathAttributes.writeByte(4); // Data length
+ pathAttributes.writeInt((int) localPref); // Preference value
+ // MULTI_EXIT_DISC: multiExitDisc
+ attrFlags = 0x80; // Optional
+ // Non-Transitive flag
+ pathAttributes.writeByte(attrFlags);
+ pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
+ pathAttributes.writeByte(4); // Data length
+ pathAttributes.writeInt((int) multiExitDisc); // Preference value
+ // The NLRI prefixes
+ encodedPrefixes = encodePackedPrefixes(addedRoutes);
+
+ // Write the Path Attributes, beginning with its length
+ message.writeShort(pathAttributes.readableBytes());
+ message.writeBytes(pathAttributes);
+ message.writeBytes(encodedPrefixes);
+
+ return prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE, message);
+ }
+
+ /**
+ * Encodes a collection of IPv4 network prefixes in a packed format.
+ * <p>
+ * The IPv4 prefixes are encoded in the form:
+ * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
+ * and Prefix is the IPv4 prefix (padded with trailing bits to the end
+ * of an octet).
+ *
+ * @param prefixes the prefixes to encode
+ * @return the buffer with the encoded prefixes
+ */
+ private ChannelBuffer encodePackedPrefixes(Collection<IpPrefix> prefixes) {
+ ChannelBuffer message =
+ ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+
+ // Write each of the prefixes
+ for (IpPrefix prefix : prefixes) {
+ int prefixBitlen = prefix.prefixLength();
+ int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
+ message.writeByte(prefixBitlen);
+
+ IpAddress address = prefix.toIpAddress();
+ long value = address.toInt() & 0xffffffffL;
+ for (int i = 0; i < IpAddress.INET_LEN; i++) {
+ if (prefixBytelen-- == 0) {
+ break;
+ }
+ long nextByte =
+ (value >> ((IpAddress.INET_LEN - i - 1) * 8)) & 0xff;
+ message.writeByte((int) nextByte);
+ }
+ }
+
+ return message;
+ }
+
+ /**
+ * Prepares BGP KEEPALIVE message.
+ *
+ * @return the message to transmit (BGP header included)
+ */
+ ChannelBuffer prepareBgpKeepalive() {
+ ChannelBuffer message =
+ ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+ return prepareBgpMessage(BgpConstants.BGP_TYPE_KEEPALIVE, message);
+ }
+
+ /**
+ * Prepares BGP NOTIFICATION message.
+ *
+ * @param errorCode the BGP NOTIFICATION Error Code
+ * @param errorSubcode the BGP NOTIFICATION Error Subcode if applicable,
+ * otherwise BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC
+ * @param payload the BGP NOTIFICATION Data if applicable, otherwise null
+ * @return the message to transmit (BGP header included)
+ */
+ ChannelBuffer prepareBgpNotification(int errorCode, int errorSubcode,
+ ChannelBuffer data) {
+ ChannelBuffer message =
+ ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
+ // Prepare the NOTIFICATION message payload
+ message.writeByte(errorCode);
+ message.writeByte(errorSubcode);
+ if (data != null) {
+ message.writeBytes(data);
+ }
+ return prepareBgpMessage(BgpConstants.BGP_TYPE_NOTIFICATION, message);
+ }
+
+ /**
+ * Prepares BGP message.
+ *
+ * @param type the BGP message type
+ * @param payload the message payload to transmit (BGP header excluded)
+ * @return the message to transmit (BGP header included)
+ */
+ private ChannelBuffer prepareBgpMessage(int type, ChannelBuffer payload) {
+ ChannelBuffer message =
+ ChannelBuffers.buffer(BgpConstants.BGP_HEADER_LENGTH +
+ payload.readableBytes());
+
+ // Write the marker
+ for (int i = 0; i < BgpConstants.BGP_HEADER_MARKER_LENGTH; i++) {
+ message.writeByte(0xff);
+ }
+
+ // Write the rest of the BGP header
+ message.writeShort(BgpConstants.BGP_HEADER_LENGTH +
+ payload.readableBytes());
+ message.writeByte(type);
+
+ // Write the payload
+ message.writeBytes(payload);
+ return message;
+ }
+}